【问题标题】:Trouble downloading binary file with angular $http or jquery.ajax使用角度 $http 或 jquery.ajax 下载二进制文件时遇到问题
【发布时间】:2016-01-13 00:56:12
【问题描述】:

我的问题是我在客户端获取了错误大小的文件。这是我的@Controller ...

@RequestMapping(value = "/download/{id}", method = RequestMethod.GET)
public ResponseEntity<?> download(final HttpServletRequest request,
                                  final HttpServletResponse response,
                                  @PathVariable("id") final int id) throws IOException {
    try {
        // Pseudo-code for retrieving file from ID.
        Path zippath = getZipFile(id);

        if (!Files.exists(zippath)) {
            throw new IOException("File not found.");
        }

        ResponseEntity<InputStreamResource> result;
        return ResponseEntity.ok()
                             .contentLength(Files.size(zippath))
                             .contentType(MediaType.APPLICATION_OCTET_STREAM)
                             .body(new InputStreamResource(new FileInputStream(zippath.toFile())));
    } catch (Exception ex) {
        // ErrorInfo is another class, unimportant
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorInfo(ex));
    }
}

...这是我使用 angular-file-saver 的客户端代码...

$http({url: "export/download/" + exportitem.exportId, withCredentials: true})
.then(function(response) {
    function str2bytes(str) {
        var bytes = new Uint8Array(str.length);
        for (var i=0; i<str.length; i++) {
            bytes[i] = str.charCodeAt(i);
        }
        return bytes;
    }
    var blob = new Blob([str2bytes(response.data)], {type: 'application/octet-stream'});
    FileSaver.saveAs(blob, "download.zip");
}, $exceptionHandler);

原始文件为 935673 字节,但 response.data 为 900728,并将其通过转换传递给 Uint8Array 会产生一个大小为 900728 的 Blob。无论哪种方式,生成的保存文件都是 900728 字节(34945 字节)。此外,它所写的内容也不完全相同。它似乎有点臃肿,但最后一部分似乎被截断了。有什么想法我可能做错了吗?

更新

我刚刚将我的控制器方法更新为以下并得到完全相同的结果。咕噜。

@RequestMapping(value = "/download/{id}", method = RequestMethod.GET)
public void download(final HttpServletRequest request,
                     final HttpServletResponse response,
                     @PathVariable("id") final int id) throws IOException {
    // Pseudo-code for retrieving file from ID.
    Path zippath = getZipFile(id);

    if (!Files.exists(zippath)) {
        throw new IOException("File not found.");
    }

    response.setContentType("application/zip");
    response.setHeader("Content-Disposition",
                        "attachment; filename=download.zip");

    InputStream inputStream = new FileInputStream(zippath.toFile());
    org.apache.commons.io.IOUtils.copy(inputStream, response.getOutputStream());
    response.flushBuffer();
    inputStream.close();
}

【问题讨论】:

  • zippath.toFile() 会发生什么?
  • 将 Path 对象转换为 File 对象,以便我可以在 FileInputStream 中使用它。

标签: java angularjs spring zipfile


【解决方案1】:

所以问题原来是 Angular 的 $http 服务。我还尝试了 jQuery 的 ajax 方法。两者都给出了相同的结果。如果我改为使用本机 XMLHttpRequest 它可以正常工作。所以 Java 代码是正确的。我首先通过将文件直接暴露在互联网上来验证这一点,然后使用 curl 和直接在浏览器中访问我设法下载了正确大小的文件。然后我找到了这个解决方案,这样我也可以通过 javascript 下载文件。

var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob";
xhr.withCredentials = true;
xhr.onreadystatechange = function (){
    if (xhr.readyState === 4) {
        var blob = xhr.response;
        FileSaver.saveAs(blob, filename);
    }
};
xhr.send();

为什么 Angular 或 jQuery 会给出错误的结果?我仍然不知道,但是如果有人希望给出使用这些答案的答案,将不胜感激。

【讨论】:

  • 同样的事情。不知道为什么 jquery/angular 会增加文件大小并破坏数据。
【解决方案2】:

响应类型:blob 做了一个 zip 文件的技巧

角度 2 +

this.http.get('http://localhost:8080/export', { responseType: ResponseContentType.Blob })
  .subscribe((res: any) => {
        const blob = new Blob([res._body], { type: 'application/zip' });
         saveAs(blob, "fileName.zip");

【讨论】:

    【解决方案3】:

    我刚刚偶然发现 $http 请求中的“responseType”,您可能正在寻找“blob”:https://docs.angularjs.org/api/ng/service/$http#usage

    【讨论】:

      猜你喜欢
      • 2019-01-28
      • 2010-10-09
      • 2015-03-07
      • 2012-10-22
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      相关资源
      最近更新 更多