Reputation: 153
I am trying to download an excel file from server. UI is in angular 6 and service is C# Web API. Firstly, I am not getting whether this download method need to be HTTPGET or HTTPPOST. Using some help from other forum, I have written code below. I don't see any error nor I see that debugger stop inside subscribe method. when I click on file link to download from angular app the page redirect to localhost: port (start page)
[HttpGet]//http get as it return file
public HttpResponseMessage DownloadAttachment(string fileName)
{
//below code locate physical file on server
var localFilePath = HttpContext.Current.Server.MapPath("../../uploadFiles/" + fileName);
HttpResponseMessage response = null;
if (!File.Exists(localFilePath))
{
//if file not found than return response as resource not present
response = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
//if file present than read file
var fStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read);
//compose response and include file as content in it
response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
// Content = new StreamContent(fStream)
Content = new StreamContent(fStream)
};
//set content header of reponse as file attached in reponse
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = Path.GetFileName(fStream.Name)
};
//set the content header content type as application/octet-stream as it
//returning file as reponse
response.Content.Headers.ContentType = new
MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentLength = fStream.Length;
response.Headers.Add("fileName", fileName);
}
return response;
}
Now, from Angular calling:
downloadFile(fileName: string) {
this.Service.postAndGetResponse(fileName).subscribe(fileData => {
// const b: any = new Blob([fileData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
// .map(res => new Blob([res.blob()],{ type: 'application/vnd.ms-excel' }));
// const url = window.URL.createObjectURL(b);
// window.open(url);
console.log (fileData);
}
);
}
in Service.ts
postAndGetResponse(fileName) {
return this.http.get(this.baseURL + 'DataEvent/DownloadEventAttachment?fileName=' + fileName, {responseType: 'blob' as 'blob'}).pipe(
map((x) => {
return x;
})
);
}
I have put debugger in downloadFile method inside subscribe, but it never stops there as if nothing is returned or call is lost.
When I use postman to call WEB API method, the response is returned. I don't see any text format- it seems to be corrupted/binary?? the format is like below in response body:
��ࡱ�>�� �����������������
Upvotes: 1
Views: 13180
Reputation: 18975
I tried to reproduce your code. Following code is working. Change the code in postAndGetResponse only to return http get call.
You can use a link or FileSaver
to save blob content.
postAndGetResponse(fileName) {
return this.http.get('http://localhost:62292' + '/api/TestExport/DownloadAttachment?fileName=' + fileName, { responseType: 'blob' as 'blob' });
}
Update download file method
downloadFile(fileName: string) {
this.settingService.postAndGetResponse(fileName).subscribe(fileData => {
const blob: any = new Blob([fileData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
let link = document.createElement("a");
if (link.download !== undefined) {
let url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
);
}
And API code, change verb to [AcceptVerbs("GET")]
public class TestExportController : ApiController
{
[Route("api/TestExport/DownloadAttachment")]
[AcceptVerbs("GET")]
public HttpResponseMessage DownloadAttachment(string fileName)
{
//below code locate physical file on server
var localFilePath = HttpContext.Current.Server.MapPath("../../uploadFiles/" + fileName);
HttpResponseMessage response = null;
if (!File.Exists(localFilePath))
{
//if file not found than return response as resource not present
response = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
//if file present than read file
var fStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read);
//compose response and include file as content in it
response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
// Content = new StreamContent(fStream)
Content = new StreamContent(fStream)
};
//set content header of reponse as file attached in reponse
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = Path.GetFileName(fStream.Name)
};
//set the content header content type as application/octet-stream as it
//returning file as reponse
response.Content.Headers.ContentType = new
MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentLength = fStream.Length;
response.Headers.Add("fileName", fileName);
}
return response;
}
}
Upvotes: 2
Reputation: 153
I figured out that posting for someone need help with same problem:
downloadFile(fileName: string) {
const isIE = /*@cc_on!@*/false || !!document['documentMode'];
const isChrome = !!window['chrome'];
this.service.postAndGetResponse(fileName).subscribe(fileData => {
const blob: any = new Blob([fileData], { type: 'application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet' });
if (isIE) { // this code doesn't work for chrome
console.log('Manage IE download>10');
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else if (isChrome) { // this below code doesn't work for IE
const link = document.createElement('a');
if (link.download !== undefined) {
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', fileName);
link.setAttribute('target', '_self');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
} else {
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
});
}
Upvotes: 1