I develop a web API with ASP.NET C# and angular 8. I try to export some data from Oracle into Excel file on the server-side (using NPOI) and download it in client-side. I can see that the memoryStream have the data but on the "return response" it doesnt returned to the client and instead of it the function is called again. This is my code:
HTML:
<button
class="col-sm-2 button-style button-text"
style="color: white; background-color: #19D893;height: 100%;"
(click)="exportPriceList()">
Export
</button>
type script:
public exportPriceList(): void {
let fileName='filename';
const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
console.log('before promise');
const promise = new Promise((resolve, reject) => {
this.export().subscribe(
success => {
console.log('start success');
const blob = new Blob ([success], {type: fileType});
console.log('window.navigator ', window.navigator );
console.log('window.navigator.msSaveOrOpenBlob ', window.navigator.msSaveOrOpenBlob );
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, );
} else {
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName ;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
},
err => {
alert(err);
});
});
promise.then((res) => {
console.log('promise!!!! ', res );
});
promise.catch((err) => {
});
}
public export()
{
console.log('start export to excel');
const fileName = 'filename1';
const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
const url = this.apiService.baseUrl + 'api/PriceList/Export?token=' + this.auth.authDetails.getValue().token +
'&priceListType=' + this.selectedPriceListType.Key + '&fileType=' + fileType + '&bank=' + this.selectedBank.Key;
return this.http.get(url, {responseType: 'arraybuffer'});// this.http.get(url, {responseType: 'blob'});
}
API Controller:
[HttpGet]
[Route("api/PriceList/Export")]
public HttpResponseMessage Export([FromUri]string token, [FromUri]int priceListType,[FromUri]string fileType, [FromUri]int? bank=null)
{
try
{
var stream = dal.ExportPriceListServer(priceListType, bank);
var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName= "PriceList_" + bank + "_" + DateTime.Now.ToString("yyyyMMdd") + ".xlsx"
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue(fileType);
return response;
}
catch (Exception ex)
{
exc.throwException(EventLogEntryType.Error, ex.ToString());
throw;
}
}
DAL: (The final function which generate the excel.)
public MemoryStream ExportToExcel(DataTable dt)
{
try
{
using (var stream = new MemoryStream())
{
// Declare XSSFWorkbook object for create sheet
var workbook = new XSSFWorkbook();
var sheet = workbook.CreateSheet("sheet 1");
int rowIndex = 0;
var headerRow = sheet.CreateRow(1);
//Below loop is create header
foreach (DataColumn column in dt.Columns)
{
XSSFCell xc = (XSSFCell)headerRow.CreateCell(column.Ordinal);
xc.SetCellValue(GetColumnTitle(column.ColumnName));
//xc.CellStyle = xstl;
}
rowIndex = 2;
foreach (DataRow row in dt.Rows)
{
XSSFRow dataRow = (XSSFRow)(sheet.CreateRow(rowIndex));
foreach (DataColumn column in dt.Columns)
{
XSSFCell c = (XSSFCell)dataRow.CreateCell(column.Ordinal);
string val = row[column].ToString();
int x;
if (Int32.TryParse(val, out x) && (!String.IsNullOrEmpty(val)))//column.IsNumeric()
{
c.SetCellValue(Int64.Parse(val));
c.SetCellType(CellType.Numeric);
}
else
{
c.SetCellValue(row[column].ToString());
}
// no need to auto size all the time, after 100 is ok... (it costs a lot)
if (rowIndex == 100)
{
sheet.AutoSizeColumn(column.Ordinal);
}
}
rowIndex++;
}
// Declare one MemoryStream variable for write file in stream
workbook.Write(stream, true);
return stream;
}
}
catch (Exception ex)
{
Console.Write(ex);
return null;
}
}
This is what I see in chrome debugger: [Network][1]
In Timing I see "Stallen": [Stallen][2]
rates.component.ts:100 before promise zone.js:2969 GET ..... **net::ERR_CONNECTION_RESET** scheduleTask @ zone.js:2969 push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:407 onScheduleTask @ zone.js:297 push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:401 push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:232 push../node_modules/zone.js/dist/zone.js.Zone.scheduleMacroTask @ zone.js:255 scheduleMacroTaskWithCurrentZone @ zone.js:1114 (anonymous) @ zone.js:3001 proto.<computed> @ zone.js:1394 (anonymous) @ http.js:1630 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe
@ Observable.js:43 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:29 push../node_modules/rxjs/_esm5/internal/operators/finalize.js.FinallyOperator.call @ finalize.js:13 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:24 (anonymous) @ subscribeTo.js:21 subscribeToResult @ subscribeToResult.js:11 push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._innerSub @ mergeMap.js:74 push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._tryNext @ mergeMap.js:68 push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._next @ mergeMap.js:51 push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54 (anonymous) @ scalar.js:5 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe @ Observable.js:43 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:29 push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapOperator.call @ mergeMap.js:29 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:24 push../node_modules/rxjs/_esm5/internal/operators/filter.js.FilterOperator.call @ filter.js:15 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:24 push../node_modules/rxjs/_esm5/internal/operators/map.js.MapOperator.call @ map.js:18 push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe @ Observable.js:24 (anonymous) @ rates.component.ts:144 ZoneAwarePromise @ zone.js:891 push../src/app/Components/content/rates/rates.component.ts.RatesComponent.exportPriceList @ rates.component.ts:143 eval @ RatesComponent.html:100 handleEvent @ core.js:19545 callWithDebugContext @ core.js:20639 debugHandleEvent @ core.js:20342 dispatchEvent @ core.js:16994 (anonymous) @ core.js:17441 (anonymous) @ platform-browser.js:993 push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:421 onInvokeTask @ core.js:14051 push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:420 push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:188 push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:496 invokeTask @ zone.js:1540 globalZoneAwareCallback @ zone.js:1566
Do you have any solution for me?
Thanks,