我正在从Angular2客户端将JSON格式的数据发送到服务器,并期望得到ZIP文件。
我已经编写了一个JAX-RS方法来生成一个ZIP文件,并将其放入/ tmp目录中进行下载。我从客户端获取JSON downloadInfo或生成ZIP文件都没有问题,因此在此示例中我跳过了这些内容。此示例所做的全部工作就是发送一个响应,该响应是一个预先创建的ZIP文件。
@Consumes({MediaType.APPLICATION_JSON})
@POST
@Path("test-download")
@Produces("application/octet-stream")
public Response getZip(String downloadInfo,
@Context SecurityContext securityContext)
{
System.out.println("downloadInfo=" + downloadInfo);
File zipFile = new File("/tmp/file.zip");
return Response.ok(zipFile)
.header("Content-Disposition", "attachment; filename=" + zipFile.getName())
.build();
}
我正在使用具有GET覆盖的POST,因为我需要在请求中发送大量数据,并且某些请求数据包含无法进行URL编码的字符。请求数据未在此处显示。以下是相关的Angular2代码:
downloadZip(): void {
let downloadZipUrl = 'http://myserver/test-download';
let json: any = {};
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('responseType', ResponseContentType.Blob);
headers.append('X-HTTP-Method-Override', 'GET');
this.http.post(downloadZipUrl, json, {headers: headers}).subscribe(response => {
var blob = new Blob([response['_body']], {type: 'application/zip'});
var url= URL.createObjectURL(blob);
window.open(url);
});
}
运行此命令时,我确实下载了ZIP文件,但该ZIP文件似乎已损坏。如果将下载的文件“吸引”到屏幕上,则会看到一堆Unicode替换字符(菱形中的问号)。如果我“抓住”原始ZIP,则看不到这些字符。另外,下载文件的大小大于原始文件的大小。
我对此进行了大量研究,并尝试了Angular2客户端和JAX-RS服务器中各种媒体类型(应用程序/八位字节流,应用程序/ zip)的化身,以及客户端中的字符集的所有化身。无济于事。
更新10/4/2018
如果我使用浏览器(没有Angular2客户端)访问URL,则ZIP会正确下载。这表明Angular2方面存在问题。
答案 0 :(得分:0)
解决方案
我已经开始工作了。这是我的解决方案。后端JAX-RS方法:
@Consumes({MediaType.APPLICATION_JSON})
@POST
@Path("test-download")
@Produces("application/zip")
public Response getZip(String downloadInfo,
@Context SecurityContext securityContext)
{
System.out.println("downloadInfo=" + downloadInfo);
File zipFile = new File("/tmp/file.zip");
return Response.ok(zipFile)
.header("Content-Disposition", "attachment; filename=" + zipFile.getName())
.build();
}
JAX-RS方法从问题到解决方案的变化是什么?真的没什么。我确实将“ application / octet-stream”更改为“ application / zip”,但我同时测试了这两种方法。
Angular2代码:
downloadZip(): void {
let downloadZipUrl = 'http://myserver/test-download';
let json: any = {};
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('X-HTTP-Method-Override', 'GET');
let options = new RequestOptions({responseType: ResponseContentType.Blob});
options.headers = headers;
this.http.post(downloadZipUrl, json, options).subscribe(response => {
// Get the file name from the content disposition.
let contentDisposition = response.headers.get('Content-Disposition');
let fileName = contentDisposition.split(';')[1].trim().split('=')[1];
fileName = fileName.replace(/"/g, ''); // Get rid of double quotes.
// Get and automatically download the file.
let blob = new Blob([response._body], {type: 'application/zip'});
let downloadLink = document.createElement('a');
let url = URL.createObjectURL(blob);
downloadLink.setAttribute('href', url);
downloadLink.setAttribute('download', fileName);
downloadLink.style.visibility = 'hidden';
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
}
是什么与众不同?使用RequestOptions:
let options = new RequestOptions({responseType: ResponseContentType.Blob});
我曾经尝试过放置:
{responseType: ResponseContentType.Blob}
在http.post调用本身中,但是对我而言不起作用。也许我做错了。