I am trying to develop a file download using angular 7. I am using HttpClient
and FileSaver
for download. The problem I am having is that, when the HttpClient makes the download request to the server, it waits for the entire response to be completed (keeps the entire file in browser memory) and the save dialogue
appears only at the end. I believe in case of large files, storing it in memory will cause problem. Is there a way I can show the save dialogue
as soon as the status OK is received and stream the file to the filesystem. I also need to send the authorization header with the request.
My server side code:
@RequestMapping(value = "/file/download", method = RequestMethod.GET)
public void downloadReport(@RequestParam("reportId") Integer reportId, HttpServletResponse response) throws IOException {
if (null != reportId) {
JobHandler handler = jobHandlerFactory.getJobHandler(reportId);
InputStream inStream = handler.getReportInputStream();
response.setContentType(handler.getContentType());
response.setHeader("Content-Disposition", "attachment; filename=" + handler.getReportName());
FileCopyUtils.copy(inStream, response.getOutputStream());
}
}
My Client code (angular)
downloadLinksByAction(id, param) {
this._httpClient.get(AppUrl.DOWNLOAD, { params: param, responseType: 'blob', observe: 'response' }).subscribe((response: any) => {
const dataType = response.type;
const filename = this.getFileNameFromResponseContentDisposition(response);
const binaryData = [];
binaryData.push(response.body);
const blob = new Blob(binaryData, { type: dataType });
saveAs(blob, filename);
}, err => {
console.log('Error while downloading');
});
}
getFileNameFromResponseContentDisposition = (res: Response) => {
const contentDisposition = res.headers.get('content-disposition') || '';
const matches = /filename=([^;]+)/ig.exec(contentDisposition);
return matches && matches.length > 1 ? matches[1] : 'untitled';
};