java 대용량 - 스프링 컨트롤러에서 파일 다운로드하기




자바 이미지 (9)

웹 사이트에서 PDF를 다운로드해야하는 요구 사항이 있습니다. PDF는 freemarker와 iText와 같은 PDF 생성 프레임 워크의 조합으로 생각되는 코드 내에서 생성되어야합니다. 더 좋은 방법이 있니?

그러나, 내 주요 문제는 어떻게 사용자가 스프링 컨트롤러를 통해 파일을 다운로드하도록 허용 하는가?


Answers

Spring 3.0을 사용하면 HttpEntity 반환 객체를 사용할 수 있습니다. 이것을 사용하면 컨트롤러에 HttpServletResponse 객체가 필요하지 않으므로 테스트하기가 쉽습니다. 이것을 제외하고,이 대답은 Infeligo와 상대적으로 같습니다 .

pdf 프레임 워크의 반환 값이 바이트 배열 인 경우 (다른 반환 값에 대한 내 대답의 두 번째 부분 읽기) :

@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 도없는 경우 먼저 바이트 배열로 지정 하지 않는 것이 좋습니다. 대신 다음을 사용하는 것이 좋습니다.

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

나에게 적합한 다음 솔루션

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

    }

만약 너라면:

  • 응답에 보내기 전에 전체 파일을 byte[] 에로드하고 싶지는 않습니다.
  • InputStream 을 통해 전송 / 다운로드 할 필요가 있습니다.
  • 전송 된 MIME 유형 및 파일 이름을 완벽하게 제어하고 싶습니다.
  • 다른 @ControllerAdvice 예외를 @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 대한 문서를 확인하십시오.


나는 ResourceHttpMessageConverter와 함께 Spring에 내장 된 지원을 사용하여 라인을 스트리밍 할 수 있었다. 이것은 mime-type을 결정할 수 있다면 content-length와 content-type을 설정합니다.

@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() 를 수행해야한다는 것을 잊지 마십시오.


아래처럼

@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를 표시하거나 here 예제를 다운로드 할 수 있습니다.


이 코드는 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 = "/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");

다른 답변에 정확히 반영되지 않은 약간의 변형을 추가합니다.

file_path존재 None또는 빈 문자열 의 경우를 처리 합니다.

def file_exists(file_path):
    if not file_path:
        return False
    elif not os.path.isfile(file_path):
        return False
    else:
        return True

Shahbaz에서 제안을 기반으로 변형을 추가

def file_exists(file_path):
    if not file_path:
        return False
    else:
        return os.path.isfile(file_path)

Peter Wood의 제안을 기반으로 변형 추가

def file_exists(file_path):
    return file_path and os.path.isfile(file_path):




java spring file download controller