假设有一个接口返回excel文件,我们前段需要请求这个接口获得这个文件,然后保存到本地,达到下载的效果。
首先我们是需要去调用这个接口的,接口返回的body里面是一个excel文件。
在Angular中使用HttpClient
处理的GET/POST请求都是json数据格式的处理,那文件响应如何处理?
1 | get( |
在Angular中有15重重载:
observe: 'body';
,responseType: 'arraybuffer';
return Observable<ArrayBuffer>
。observe: 'body';
,responseType: 'blob';
return Observable<Blob>
。observe: 'body';
,responseType: 'text';
return Observable<string>
。observe: 'body';
,responseType: 'json';
return Observable<Object>
。observe: 'body';
,responseType: 'json';
return Observable<T>
。observe: 'events';
,responseType: 'arraybuffer';
return Observable<ArrayBuffer>
。observe: 'events';
,responseType: 'blob';
return Observable<Blob>
。observe: 'events';
,responseType: 'text';
return Observable<string>
。observe: 'events';
,responseType: 'json';
return Observable<HttpEvent<Object>>
。observe: 'events';
,responseType: 'json';
return Observable<HttpEvent<T>>
。observe: 'response';
,responseType: 'arraybuffer';
return Observable<HttpResponse<ArrayBuffer>>
。observe: 'response';
,responseType: 'blob';
return Observable<HttpResponse<Blob>>
。observe: 'response';
,responseType: 'text';
return Observable<HttpResponse<string>>
。observe: 'response';
,responseType: 'json';
return Observable<HttpResponse<Object>>
。observe: 'response';
,responseType: 'json';
return Observable<HttpResponse<T>>
。
发现正好有我们需要的重载,我们需要监听response
,并且返回的body
里面是Blob
,那么我们可以这样发起一个请求:
1 | export class TestComponent implements OnInit { |
这里需要看下HttpResponse
, 它有个属性type
:
Sent = 0
请求通过网络发送UploadProgress = 1
接收到上传事件ResponseHeader = 2
接收到响应状态码和标头DownloadProgress = 3
收到下载进度事件Response = 4
收到body在内的所有响应User = 5
来自拦截器或后端的自定义事件(哦哟,这个好像很有意思🤔)
也就是说我们监测到HttpResponse.type === 4
的时候才可以去处理响应里面的Blob
:
1 | this._http.post(url, params, { |
处理下载
HTML中的<a>
标签我们一般来用于导航,但它有一个很有用的属性download
。这个属性指示浏览器下载URL而不是导航到它,因此将提示用户将其保存为本地文件。如果download
属性有一个值,那么这个值将在下载保存过程中作为预填充的文件名(如果用户需要,仍然可以修改保存的文件名)。此属性对允许的值没有限制,但是/
和\
会被转换为下划线。大多数文件系统限制了文件中的标点符号,故此,浏览器将响应的调整建议的文件名。参考MDN 标签。
需要注意的是,这个熟悉仅适用于同源URL。当然我们可以使用blob: URL
和data: URL
以方便用户下载使用JavaScript生成的内容(比如使用canvas
生成的图片等)。
如果HTTP响应头信息中有属性Content-Diposition
设置了文件名,那么浏览器会优先使用此属性。
那我们可以来完成下载逻辑:
1 | const objUrl = window.URL.createObjectURL(res.body); |
最终代码:
1 | export class TestComponent implements OnInit { |
梳理代码,也是整理和排查不清楚的地方。