2016-01-13 72 views
1

我的问题是我在客户端获取大小错误的文件。这是我@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)); 
    } 
} 

...这里是采用了棱角分明文件金丹我的客户端代码......

$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个字节,但响应.data是900728并将其传递给Uint8Array转换,结果产生一个大小为900728的Blob。无论哪种方式,结果保存的文件是900728字节(34945字节害羞)。它的写作内容也不尽相同。它似乎有点臃肿,但最后一部分似乎被截断。任何想法我可能做错了什么?

UPDATE

我刚刚更新了我的控制方法是以下,得到了完全相同的结果。哎呀。

@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(); 
} 
+0

什么'zippath.toFile()'会发生什么? – domoarrigato

+0

将Path对象转换为File对象,以便我可以在FileInputStream中使用它。 – crowmagnumb

回答

3

所以问题原来是角的$ 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会给出错误的结果?我仍然不知道,但如果任何人想给出一个答案,使用它将不胜感激。

+0

同样的事情。不知道为什么jquery/angular会增加文件大小并破坏数据。 – dejavu

1

的responseType: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");