2013-11-09 1 views
1

안녕하세요, 다음과 같이 작성된 컨트롤러 클래스가 있습니다. mongo db에서 파일을 가져 와서 다운로드하려고합니다.Spring mvc 및 mongodb에서 파일을 다운로드하는 방법

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"); 
     } 

하지만 파일을 다운로드 할 수 없습니다. 어느 누구도 나를 도와 줄 수 없다. 당신이 그것을 놓친 경우

+0

라인은'response.setCharacterEncoding (file.getMD5()); incorrecr'이다. CharacterEncoding은 "UTF-8"또는 이와 비슷한 형식이어야합니다. –

답변

1

내 GET으로 요청 및 HTML의 앵커 태그에 추가 요청을 변경했습니다. 또한 코드를 다음과 같이 변경했습니다.

@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"); 
     } 
    } 
} 

이제는 제대로 작동합니다.

4

는 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); 

없음 인코딩 만지작 그리고 당신을 위해 헤더는 그렇게합니다. 나는 너의 자신을 굴리기 전에 그것을 시도하는 것이 좋습니다.

편집 : 위의 봄 3.1.4에서 잘 작동했다. 3.2.x 또는 4.x에서는 더 이상 작동하지 않습니다. 이전에 produce = {MediaType.APPLICATION_OCTET_STREAM_VALUE}가 Spring에게 적절한 헤더를 추가하게 만들었지 만, 이제는 제한으로 취급합니다. 표준 웹 브라우저로 URL에 액세스하는 경우 "application/octet-stream"의 수락 헤더가 전송되지 않습니다. 따라서 Spring은 406 오류를 반환합니다. 다시 작동 시키려면 "produce"속성없이 다시 작성해야합니다. 대신 메서드 인수에 HttpServletResponse를 추가하고 메서드 내부에 헤더를 추가합니다. 즉 :

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

편집 REDUX : 지금 봄 부팅 1.1.8을 통해 봄 4.0.7를 사용. produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE } 명령어 설정이 다시 작동하는 것으로 보입니다. 그 지시만으로도 내가 시도한 모든 브라우저에 충분할 것 같습니다. 그러나 나는 으로 남겨진 Content-Disposition을 설정하지 않는다는 것을 발견했습니다. 이것은 브라우저에서 문제가되지는 않지만 PHP 클라이언트 애플리케이션에서는 버그를 발견했습니다. 이는 Content-Disposition만을 기반으로 동작합니다. 그래서 현재의 해결책은 위의 두 가지를하는 것입니다!

관련 문제