Загрузка файла с контроллеров spring
У меня есть требование, где мне нужно скачать PDF с сайта. PDF должен быть сгенерирован в коде, который, как я думал, будет комбинацией freemarker и структуры генерации PDF, такой как iText. Есть ли лучший способ?
однако моя главная проблема заключается в том, как я могу позволить пользователю загружать файл через контроллер Spring?
10 ответов:
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET) public void getFile( @PathVariable("file_name") String fileName, HttpServletResponse response) { try { // get your file as InputStream InputStream is = ...; // copy it to response's OutputStream org.apache.commons.io.IOUtils.copy(is, response.getOutputStream()); response.flushBuffer(); } catch (IOException ex) { log.info("Error writing file to output stream. Filename was '{}'", fileName, ex); throw new RuntimeException("IOError writing file to output stream"); } }вообще говоря, когда у вас есть
response.getOutputStream(), вы можете написать что-нибудь. Вы можете передать этот выходной поток как место для размещения сгенерированного PDF в свой генератор. Кроме того, если вы знаете, какой тип файла вы отправляете, вы можете установитьresponse.setContentType("application/pdf");
Я был в состоянии потоковой линии это с помощью встроенной поддержки весной с его ResourceHttpMessageConverter. Это установит длину содержимого и тип содержимого, если он может определить тип mime
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET) @ResponseBody public FileSystemResource getFile(@PathVariable("file_name") String fileName) { return new FileSystemResource(myService.getFileFor(fileName)); }
вы должны быть в состоянии записать файл на ответ напрямую. Что-то вроде
response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\"");а затем записать файл в виде двоичного потока на
response.getOutputStream(). Не забудьте сделатьresponse.flush()в конце концов, и это должно сделать это.
С Spring 3.0 вы можете использовать
HttpEntityвозвращает объект. Если вы используете это, то ваш контроллер не нуженHttpServletResponse"объект", и поэтому его легче проверить. кроме этого, этот ответ относительно равен одному из Infeligo.если возвращаемое значение вашего PDF framework является массивом байтов (читай вторую часть моего ответа для других возвращаемых значений):
@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET) public HttpEntity<byte[]> createPdf( @PathVariable("fileName") String fileName) throws IOException { byte[] documentBody = this.pdfFramework.createPdf(filename); HttpHeaders header = new HttpHeaders(); header.setContentType(MediaType.APPLICATION_PDF); header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName.replace(" ", "_")); header.setContentLength(documentBody.length); return new HttpEntity<byte[]>(documentBody, header); }
если возвращаемый тип вашего PDF Рамки (
documentBbody) еще не является массивом байтов (и нетByteArrayInputStream) тогда было бы мудро не чтобы сначала сделать его массивом байтов. Вместо этого лучше использовать:
InputStreamResource,PathResource(С весны 4.0) илиFileSystemResource,пример
FileSystemResource:@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET) public HttpEntity<byte[]> createPdf( @PathVariable("fileName") String fileName) throws IOException { File document = this.pdfFramework.createPdf(filename); HttpHeaders header = new HttpHeaders(); header.setContentType(MediaType.APPLICATION_PDF); header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName.replace(" ", "_")); header.setContentLength(document.length()); return new HttpEntity<byte[]>(new FileSystemResource(document), header); }
если вы:
- не хочу загружать весь файл в
byte[]перед отправкой в ответ;- хотите / нужно отправить / загрузить его через
InputStream;- хотите иметь полный контроль над типом Mime и именем файла, отправленного;
- другие
@ControllerAdviceсбор исключений для вас.ниже приведен код, что вам нужно:
@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET) public ResponseEntity<InputStreamResource> downloadStuff(@PathVariable int stuffId) throws IOException { String fullPath = stuffService.figureOutFileNameFor(stuffId); File file = new File(fullPath); HttpHeaders respHeaders = new HttpHeaders(); respHeaders.setContentType("application/pdf"); respHeaders.setContentLength(12345678); respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf"); InputStreamResource isr = new InputStreamResource(new FileInputStream(file)); return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK); }также обратите внимание, что, чтобы избежать чтения всего файла просто рассчитать его длину, вам лучше сохранить его раньше. Убедитесь, что вы проверяете документы для
InputStreamResource.
этот код работает нормально, чтобы загрузить файл автоматически из spring controller при нажатии ссылки на jsp.
@RequestMapping(value="/downloadLogFile") public void getLogFile(HttpSession session,HttpServletResponse response) throws Exception { try { String filePathToBeServed = //complete file name with path; File fileToDownload = new File(filePathToBeServed); InputStream inputStream = new FileInputStream(fileToDownload); response.setContentType("application/force-download"); response.setHeader("Content-Disposition", "attachment; filename="+fileName+".txt"); IOUtils.copy(inputStream, response.getOutputStream()); response.flushBuffer(); inputStream.close(); } catch (Exception e){ LOGGER.debug("Request could not be completed at this moment. Please try again."); e.printStackTrace(); } }
ниже код работал для меня, чтобы создать и загрузить текстовый файл.
@RequestMapping(value = "/download", method = RequestMethod.GET) public ResponseEntity<byte[]> getDownloadData() throws Exception { String regData = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."; byte[] output = regData.getBytes(); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set("charset", "utf-8"); responseHeaders.setContentType(MediaType.valueOf("text/html")); responseHeaders.setContentLength(output.length); responseHeaders.set("Content-disposition", "attachment; filename=filename.txt"); return new ResponseEntity<byte[]>(output, responseHeaders, HttpStatus.OK); }
то, что я могу быстро придумать, это сгенерировать pdf и сохранить его в webapp/downloads/.pdf из кода и отправить вперед в этот файл с помощью HttpServletRequest
request.getRequestDispatcher("/downloads/<RANDOM-FILENAME>.pdf").forward(request, response);или если вы можете настроить ваш взгляд, арбитр что-то вроде
<bean id="pdfViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="order" value=”2″/> <property name="prefix" value="/downloads/" /> <property name="suffix" value=".pdf" /> </bean>тогда просто верните
return "RANDOM-FILENAME";
что-то вроде ниже
@RequestMapping(value = "/download", method = RequestMethod.GET) public void getFile(HttpServletResponse response) { try { DefaultResourceLoader loader = new DefaultResourceLoader(); InputStream is = loader.getResource("classpath:META-INF/resources/Accepted.pdf").getInputStream(); IOUtils.copy(is, response.getOutputStream()); response.setHeader("Content-Disposition", "attachment; filename=Accepted.pdf"); response.flushBuffer(); } catch (IOException ex) { throw new RuntimeException("IOError writing file to output stream"); } }вы можете отобразить PDF или загрузить его примеры здесь
следующее решение работает для меня
@RequestMapping(value="/download") public void getLogFile(HttpSession session,HttpServletResponse response) throws Exception { try { String fileName="archivo demo.pdf"; String filePathToBeServed = "C:\software\Tomcat 7.0\tmpFiles\"; File fileToDownload = new File(filePathToBeServed+fileName); InputStream inputStream = new FileInputStream(fileToDownload); response.setContentType("application/force-download"); response.setHeader("Content-Disposition", "attachment; filename="+fileName); IOUtils.copy(inputStream, response.getOutputStream()); response.flushBuffer(); inputStream.close(); } catch (Exception exception){ System.out.println(exception.getMessage()); } }
Comments