簡體   English   中英

如何在Spring MVC和MongoDB中下載文件

[英]How to download file in Spring mvc and mongodb

嗨,我寫了如下的控制器類。 我正在嘗試從mongo db獲取文件並嘗試下載它。

    organizationFileAttachmentService.setUser(getUser());
    GridFSDBFile file = organizationFileAttachmentService.getGridFSDBFileById(new ObjectId(id), "File");
    if (file != null) {
        byte[] content = organizationFileAttachmentService.findByIdAndBucket(new ObjectId(id), "File");
        try {
            int size = content.length;
            InputStream is = null;
            byte[] b = new byte[size];
            try {
                is = new ByteArrayInputStream(content);
                is.read(b);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (is != null)
                        is.close();
                } catch (Exception ex) {

                }
            }
            response.setContentType(file.getContentType());
            // String attachment =
            // "attachment; filename=\""+file.getFilename()+"\"";
            String attachment = "attachment; filename=" + file.getFilename();
            // response.setContentLength(new
            // Long(file.getLength()).intValue());
            response.setCharacterEncoding(file.getMD5());
            response.setHeader("content-Disposition", attachment);// "attachment;filename=test.xls"
            // copy it to response's OutputStream
            // FileCopyUtils.copy(is, response.getOutputStream());
            IOUtils.copy(is, response.getOutputStream());
            response.flushBuffer();
            is.close();
        } catch (IOException ex) {
            _logger.info("Error writing file to output stream. Filename was '" + id + "'");
            throw new RuntimeException("IOError writing file to output stream");
        }

但我無法下載文件。 誰能幫我。

萬一您錯過了它,Spring提供了各種內置的資源處理程序。

http://docs.spring.io/spring/docs/3.2.5.RELEASE/spring-framework-reference/html/resources.html#resources-implementations

如果您的方法返回其中一個(也許是ByteArrayResource),那么您只需要在接口上添加幾個注釋,如下所示:

@RequestMapping(value = "/foo/bar/{fileId}", 
    method = RequestMethod.GET, 
    produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE })
@ResponseBody FileSystemResource downloadFile(Long fileId);

這樣就不必為編碼和標頭擺弄了。 我建議您在自己動手之前嘗試一下。

編輯:上面的工作在Spring 3.1.4中很好。 它不再適用於3.2.x或4.x。 以前,produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE}會導致Spring添加適當的標頭,但現在將其視為限制。 如果使用標准的Web瀏覽器訪問URL,則不會發送“ application / octet-stream”的接受標頭。 因此,Spring將返回406錯誤。 為了使它再次工作,需要重寫這種方法而沒有“ produces”屬性。 而是將HttpServletResponse添加到方法參數中,並將標頭添加到方法內部。 即:

@RequestMapping(value = "/foo/bar/{fileId}", 
    method = RequestMethod.GET)
@ResponseBody FileSystemResource downloadFile(
            Long fileId, HttpServletResponse response) {
    ...
    response.setHeader( "Content-Disposition", "attachment;filename=" + fileName );
    ...
}

編輯redux:現在通過Spring Boot 1.1.8使用Spring 4.0.7。 似乎設置了produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE }指令現在又可以工作了。 對於所有我嘗試過的瀏覽器來說,僅具有該指令就足夠了。 但是請注意,我還發現它沒有設置Content-Disposition ,它保留為application/json 盡管對於瀏覽器來說這似乎不是問題,但我遇到了PHP客戶端應用程序中的錯誤,這些錯誤似乎僅基於Content-Disposition 因此,當前的解決方案似乎是同時完成以上兩項!

我已將請求更改為GET,並在html的錨標記中添加了請求。 Aslo將我的代碼更改為

@RequestMapping(value = "/getFileById/{id}", method = RequestMethod.GET)
public @ResponseBody
void download(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) throws IOException {
    organizationFileAttachmentService.setUser(getUser());
    GridFSDBFile file = organizationFileAttachmentService.getGridFSDBFileById(new ObjectId(id), "File");
    if (file != null) {
        try {
            response.setContentType(file.getContentType());
            response.setContentLength((new Long(file.getLength()).intValue()));
            response.setHeader("content-Disposition", "attachment; filename=" + file.getFilename());// "attachment;filename=test.xls"
            // copy it to response's OutputStream
            IOUtils.copyLarge(file.getInputStream(), response.getOutputStream());
        } catch (IOException ex) {
            _logger.info("Error writing file to output stream. Filename was '" + id + "'");
            throw new RuntimeException("IOError writing file to output stream");
        }
    }
}

現在對我來說很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM