Spring文件下载问题

时间:2018-03-26 11:09:33

标签: spring

我正在使用弹簧4.3.14

我面临一个奇怪的问题。我只是想通过使用控制器下载文件,但是当我使用InputStreamResource时,下载的文件已损坏。 这是我的WebMvcConfig:

public class SpringConfig extends WebMvcConfigurerAdapter {

 @Override
 public void configureMessageConverters(List < HttpMessageConverter < ? >> converters) {
  converters.add(new ResourceHttpMessageConverter());
 }

}

我写了以下方法:

@RequestMapping(value = "/download", method = {RequestMethod.GET})
public ResponseEntity < InputStreamResource > download() {
 try {
  File f = new File("/home/angelo/Scrivania/modulo.pdf");
  int dimensione = (int) f.length();
  InputStream is = new FileInputStream(f);
  HttpHeaders respHeaders = new HttpHeaders();
  String mi = mimeSvc.getMimeType(fileName, is);
  MediaType mime = MediaType.parseMediaType(mi);
  respHeaders.setContentType(mime);
  respHeaders.setContentDispositionFormData("attachment", fileName);
  respHeaders.setContentLength(dimensione);
  InputStreamResource result = new InputStreamResource(is);
  return new ResponseEntity < InputStreamResource > (result, respHeaders, HttpStatus.OK);
 } catch (Exception e) {

  if (logger.isErrorEnabled()) {
   logger.error("Errore nel download del manuale", e);
  }
  return new ResponseEntity < InputStreamResource > (HttpStatus.INTERNAL_SERVER_ERROR);
 }
}


@RequestMapping(value = "/download2", method = {RequestMethod.GET})
public void download2() {

 try {
  File f = new File("/home/angelo/Scrivania/modulo.pdf");
  InputStream is = new BufferedInputStream(new FileInputStream(f));
  String mi = mimeSvc.getMimeType(fileName, is);
  response.setContentType(mi);
  response.setHeader("Content-Disposition", String.format("attachment; filename=\"" + fileName + "\""));
  response.setContentLength((int) f.length());
  InputStream inputStream = new BufferedInputStream(new FileInputStream(f));
  FileCopyUtils.copy(inputStream, response.getOutputStream());
 } catch (Exception e) {
  if (logger.isErrorEnabled()) {
   logger.error("Errore nel download del manuale", e);
  }
  try {
   response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  } catch (IOException e1) {
   //Ignoro l'eccezione
  }
 }
}

通过使用第一种方法,下载的文件已损坏。通过使用第二个文件,下载的文件就可以了。我无法理解原因 这里有关于第一种方法的日志:

2018-03-26 12:59:05,949 36704 [http-nio-8080-exec-4] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.core.io.InputStreamResource> it.eng.tz.aa.suap.sue.download.manuali.controller.DownloadController.download(java.lang.String)] 2018-03-26 12:59:05,949 36704 [http-nio-8080-exec-4] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'downloadController' 2018-03-26 12:59:05,949 36704 [http-nio-8080-exec-4] TRACE o.s.web.servlet.DispatcherServlet - Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@20669e53] 2018-03-26 12:59:05,949 36704 [http-nio-8080-exec-4] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/download-manualistica/download/suap_sue/ME] is: -1 2018-03-26 12:59:05,949 36704 [http-nio-8080-exec-4] TRACE o.s.w.s.m.m.a.ServletInvocableHandlerMethod - Invoking 'it.eng.tz.aa.suap.sue.download.manuali.controller.DownloadController.download' with arguments [ME]

2018-03-26 12:59:09,325 40080 [http-nio-8080-exec-4] TRACE o.s.w.s.m.m.a.ServletInvocableHandlerMethod - Method [it.eng.tz.aa.suap.sue.download.manuali.controller.DownloadController.download] returned [<200 OK,InputStream resource [resource loaded through InputStream],{Content-Type=[application/pdf], Content-Disposition=[form-data; name="attachment"; filename="modulo.pdf"], Content-Length=[1621137]}>] 2018-03-26 12:59:09,354 40109 [http-nio-8080-exec-4] DEBUG o.s.w.s.m.m.a.HttpEntityMethodProcessor - Written [InputStream resource [resource loaded through InputStream]] as "text/html" using [org.springframework.http.converter.ResourceHttpMessageConverter@2316895c] 2018-03-26 12:59:09,354 40109 [http-nio-8080-exec-4] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'DownloadModulisticaSvlt': assuming HandlerAdapter completed request handling 2018-03-26 12:59:09,354 40109 [http-nio-8080-exec-4] TRACE o.s.web.servlet.DispatcherServlet - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@622b8367 2018-03-26 12:59:09,354 40109 [http-nio-8080-exec-4] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request 2018-03-26 12:59:09,354 40109 [http-nio-8080-exec-4] TRACE o.s.w.c.s.AnnotationConfigWebApplicationContext - Publishing event in WebApplicationContext for namespace 'DownloadModulisticaSvlt-servlet': ServletRequestHandledEvent: url=[/download-manualistica/download/suap_sue/ME]; client=[0:0:0:0:0:0:0:1]; method=[GET]; servlet=[DownloadModulisticaSvlt]; session=[null]; user=[null]; time=[3407ms]; status=[OK]

为什么这个差异在同一个文件上?

我总是使用InputStreamResource,我没有问题。

谢谢

安吉洛

1 个答案:

答案 0 :(得分:0)

在您的第一个下载方法中,您使用相同的FileInputStream两次。第二,您为每次使用创建new FileInputStream。第二种方法是正确的。

输入流应该只读一次。这就是为什么第二种方法有效,首先没有。 如果输入流支持寻求使用InputStream#reset方法“回放”流。如果支持倒带,它将解决问题。

  is.mark(0);
  is.reset();
  InputStreamResource result = new InputStreamResource(is);