Angular2使用带有GET覆盖的POST下载ZIP

时间:2018-10-01 04:59:29

标签: angular download zip jax-rs corrupt

我正在从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方面存在问题。

1 个答案:

答案 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调用本身中,但是对我而言不起作用。也许我做错了。