我有一个Angular应用程序,我需要从REST API获取文件的内容并在客户端生成文件。
由于我无法在客户端编写新文件,因此我使用this question作为解决方法。
所以基本上它的作用是创建一个包含内容的Blob并生成下载链接,然后模拟链接中的点击以便下载文档。
这是我的代码:
first key ('a'):
item = {}
first key of second loop ('a'):
is the value of 'a' a list?
no. adds the value.
new item{'a': 1}
second key of second loop ('b'):
is the value of 'b' a list?
no. adds the value.
new item{'a': 1, 'b': 2}
third key of second loop ('c'):
is the value of 'c' a list?
yes. adds the first element of the list, removing it from the list
(the list was [3, 4, 5], now is [4, 5])
new item{'a': 1, 'b': 2, 'c': 3}
appends the item to L
(the 'L' was [], now is [{'a': 1, 'b': 2, 'c': 3}])
这从服务器获取数据
download(filename) {
this.service
.downloadFile(filename)
.subscribe(data => {
console.log(data.document);
this.downloadFile(data.document, filename);
}, err => this.info = err);
}
这会构建链接并模拟要下载的点击
private downloadFile(content: string, filename: string) {
const link = document.createElement('a');
link.setAttribute('download', filename);
link.href = this.makeTextFileUrl(content, filename);
document.body.appendChild(link);
// wait for the link to be added to the document
window.requestAnimationFrame(function () {
const event = new MouseEvent('click');
link.dispatchEvent(event);
document.body.removeChild(link);
});
}
这会生成网址链接
private makeTextFileUrl(content: string, filename: string): string {
let url = null;
const mime = this.getMimeType(filename);
console.log(mime);
const blob = new Blob([content], { type: mime });
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (url !== null) {
window.URL.revokeObjectURL(url);
}
url = window.URL.createObjectURL(blob);
return url;
}
mime类型因扩展名而异
因此,这适用于纯文本文件,但是对于docx文件,当我尝试打开文件时出现错误,并且使用pdf时文件似乎是空白的。
我读到二进制文件时我需要将responseType设置为ArrayBuffer才能使其工作,所以我更新了我的服务get调用
private getMimeType(filename: string): string {
if (filename.indexOf('.docx') !== -1) return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
if (filename.indexOf('.doc') !== -1) return 'application/msword';
if (filename.indexOf('.pdf') !== -1) return 'application/pdf';
return 'text/plain';
}
但是现在我在尝试下载文件时遇到错误,无论它是txt,pdf还是docx文件downloadFile(id: string): Observable<any> {
return this.authHttp
.get(`${this.api}/download/${id}`, { responseType: ResponseContentType.ArrayBuffer })
.map(res => {
const data = res.json();
return data;
});
}
有谁知道如何解决这个问题?
由于
答案 0 :(得分:0)
所以我终于开始工作了。
事实证明我正在使用中间API Rest来获取文件的内容,然后将它们重新发送到我的前端应用程序,但是在那一步中,正文被解析为一个字符串,因此,我得到的是前端应用程序不是原始内容。
在这个帖子中解决了这个问题。 Resend body from response exactly as it comes
然后我只需要在我的前端应用程序中更改一些内容以获取二进制文件。
downloadFile(id: string): Observable<any> {
return this.authHttp
.get(`${this.api}/${id}`, { responseType: ResponseContentType.ArrayBuffer })
.map(res => {
return res.blob();
});
}
所以现在我正在检索的数据不是json而是blob。
然后在我的组件中
download(filename) {
const id = this.filesIds[filename];
this.service
.downloadFile(id)
.subscribe(blob => {
this.downloadFile(blob, filename);
}, err => this.info = err);
}
private downloadFile(blob: Blob, filename: string) {
const link = document.createElement('a');
link.setAttribute('download', filename);
link.href = this.makeTextFileUrl(blob, filename);
document.body.appendChild(link);
// wait for the link to be added to the document
window.requestAnimationFrame(function () {
const event = new MouseEvent('click');
link.dispatchEvent(event);
document.body.removeChild(link);
});
}
其余的保持不变。