我遇到了一个问题,我用Angular 1下载了一个Excel文件,但如果我在Angular 5中实现了相同的代码,则会显示文件已损坏的错误。我的回复是 ArrayBuffer ,我无法读取该文件。
以下是我的代码:
服务
DownloadData(model:requiredParams):Observable<any>{
const headers = new Headers();
const requestOptions = new RequestOptions({ headers: headers });
requestOptions.headers.append('Content-Type', 'application/json');
const body = JSON.stringify(model);
return this.http.post(url, body, requestOptions)
.map((res:any) => res)
.catch((e: any) => Observable.throw(this.errorHandler(e)));
}
组件:
exportToExcel() {
this.loadingOverlayFlag = true;
this.podashboardService.DownloadData(this.data).subscribe(result=>{
console.log(result);
this.downloadFile(result._body,'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'export.xlsx');
})
}
downloadFile(blob: any, type: string, filename: string) {
var binaryData = [];
binaryData.push(blob);
const url = window.URL.createObjectURL(new Blob(binaryData, {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})); // <-- work with blob directly
// create hidden dom element (so it works in all browsers)
const a = document.createElement('a');
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
// create file, attach to hidden element and open hidden element
a.href = url;
a.download = filename;
a.click();
}
我可以下载该文件,但无法阅读其内容。错误是:
Microsoft Excel
Excel无法打开文件&#39;███████DASHBOARD(5).xlsx&#39;因为文件格式或文件扩展名无效。 验证文件是否已损坏,以及文件扩展名是否与文件格式匹配。行
答案 0 :(得分:6)
I struggle with this one all day. Replace angular HttpClient and use XMLHttpRequest as follows:
var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.setRequestHeader("content-type", "application/json");
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
console.log(byteArray, byteArray.length);
this.downloadFile(byteArray, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'export.xlsx');
}
};
oReq.send(body);
Then modified the creation of the Blob in your downloadFile function:
const url = window.URL.createObjectURL(new Blob([binaryData]));
In your case the service will look something like this:
DownloadData(model:requiredParams):Observable<any>{
return new Observable(obs => {
var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.setRequestHeader("content-type", "application/json");
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response;
var byteArray = new Uint8Array(arrayBuffer);
obs.next(byteArray);
};
const body = JSON.stringify(model);
oReq.send(body);
});
}
Then the component:
exportToExcel() {
this.loadingOverlayFlag = true;
this.podashboardService.DownloadData(this.data).subscribe(result=>{
// console.log(result);
this.downloadFile(result,'application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet', 'export.xlsx');
})
}
downloadFile(blob: any, type: string, filename: string) {
var binaryData = [];
binaryData.push(blob);
const url = window.URL.createObjectURL(new Blob(binaryData, { type: filetype })); // <-- work with blob directly
// create hidden dom element (so it works in all browsers)
const a = document.createElement('a');
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
// create file, attach to hidden element and open hidden element
a.href = url;
a.download = filename;
a.click();
}
答案 1 :(得分:4)
我设法通过使用httpClient使其正常工作(httpOptions中的responseType: 'arraybuffer'
完成了技巧)。
createReportBackend() {
const httpOption: Object = {
observe: 'response',
headers: new HttpHeaders({
'Content-Type': 'application/json'
}),
responseType: 'arraybuffer'
};
this.httpClient.post('http://localhost:8080/api/report', this.data, httpOption)
.pipe(map((res: HttpResponse) => {
return {
filename: 'Drinks.xlsx',
data: new Blob(
[res['body']],
{ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}
),
};
}))
.subscribe(res => {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(res.data, res.filename);
} else {
const link = window.URL.createObjectURL(res.data);
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = link;
a.download = res.filename;
a.click();
window.URL.revokeObjectURL(link);
a.remove();
}
}, error => {
throw error;
}, () => {
console.log('Completed file download.');
});
}
答案 2 :(得分:0)
下载使用文件保护程序找到的exel文件的最简单方法是:
//Declaration
headers: HttpHeaders;
options: any;
//Constructor or u can have for specific method
this.headers = new HttpHeaders({ 'Content-Type': 'application/json' });
this.options = {
observe: 'response',
headers: this.headers,
responseType: 'arraybuffer'
};
//Service request:
this.httpClient.post('http://localhost:8080/api/report', this.data, this.option)
.pipe(
catchError(err => this.handleError(err))
).subscribe(response => {
Helper.exportExelFile(response, 'FileName');
});
//component or in helper function in one class
import * as FileSaver from 'file-saver';
function exportExelFile(data, filename) {
const blobValue = new Blob([data['body']], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
FileSaver.saveAs(blobValue, filename + '.' + FileType.EXCEL);
}
export const Helper = {
exportExelFile
};