Baixando um arquivo de controladores de mola

Eu tenho um requisito onde eu preciso baixar um PDF do site. O PDF precisa ser gerado dentro do código, o que eu pensei que seria uma combinação de freemarker e uma estrutura de geração de PDF como o iText. Alguma maneira melhor?

No entanto, meu principal problema é como permitir que o usuário baixe um arquivo através de um Spring Controller?

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

De um modo geral, quando você tem response.getOutputStream() , você pode escrever qualquer coisa lá. Você pode passar este stream de saída como um local para colocar PDF gerado em seu gerador. Além disso, se você souber que tipo de arquivo você está enviando, você pode definir

 response.setContentType("application/pdf"); 

Eu era capaz de transmitir isso usando o suporte embutido no Spring com o ResourceHttpMessageConverter. Isso definirá o comprimento do conteúdo e o tipo de conteúdo se ele puder determinar o tipo de mímica

 @RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET) @ResponseBody public FileSystemResource getFile(@PathVariable("file_name") String fileName) { return new FileSystemResource(myService.getFileFor(fileName)); } 

Você deve conseguir gravar o arquivo na resposta diretamente. Algo como

 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\""); 

e, em seguida, grave o arquivo como um stream binário em response.getOutputStream() . Lembre-se de fazer o response.flush() no final e isso deve ser feito.

Com o Spring 3.0, você pode usar o object de retorno HttpEntity . Se você usar isso, seu controlador não precisará de um object HttpServletResponse e, portanto, será mais fácil testá-lo. Exceto isso, esta resposta é relativa é igual à do Infeligo .

Se o valor de retorno do seu quadro pdf é uma matriz de bytes (leia a segunda parte da minha resposta para outros valores de retorno) :

 @RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET) public HttpEntity 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(documentBody, header); } 

Se o tipo de retorno de sua estrutura de PDF ( documentBbody ) ainda não é uma matriz de bytes (e também não há ByteArrayInputStream ), seria sábio NÃO fazer uma matriz de bytes primeiro. Em vez disso, é melhor usar:

  • InputStreamResource ,
  • PathResource (desde a primavera 4.0) ou
  • FileSystemResource ,

exemplo com FileSystemResource :

 @RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET) public HttpEntity 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(new FileSystemResource(document), header); } 

Se vocês:

  • Não quer carregar o arquivo inteiro em um byte[] antes de enviar para a resposta;
  • Quer / precisa enviar / fazer o download via InputStream ;
  • Deseja ter controle total do tipo MIME e nome do arquivo enviado;
  • Tenha outro @ControllerAdvice escolhendo exceções para você.

O código abaixo é o que você precisa:

 @RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET) public ResponseEntity 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(isr, respHeaders, HttpStatus.OK); } 

Observe também que, para evitar a leitura do arquivo inteiro apenas para calcular seu tamanho, é melhor que ele seja armazenado anteriormente. Certifique-se de verificar os documentos para InputStreamResource .

Este código está funcionando bem para baixar um arquivo automaticamente do controlador de mola ao clicar em um link no 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(); } } 

Abaixo do código funcionou para mim gerar e baixar um arquivo de texto.

 @RequestMapping(value = "/download", method = RequestMethod.GET) public ResponseEntity 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(output, responseHeaders, HttpStatus.OK); } 

O que posso pensar rapidamente é, gerar o pdf e armazená-lo em webapp / downloads / .pdf do código e enviar um encaminhamento para este arquivo usando HttpServletRequest

 request.getRequestDispatcher("/downloads/.pdf").forward(request, response); 

ou se você pode configurar sua visão resolver algo como

        

então é só voltar

 return "RANDOM-FILENAME"; 

algo como abaixo

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

Você pode exibir PDF ou baixar exemplos aqui

A solução a seguir funciona para mim

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