답변:
@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");
IOUtils
Spring 대신 Apache를 사용해야하는 특별한 이유는 FileCopyUtils
무엇입니까?
Spring의 내장 지원을 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));
}
Content-Disposition
이 방법으로 헤더 를 설정하는 방법이 있습니까?
응답에 파일을 직접 쓸 수 있어야합니다. 같은 것
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\"");
파일을에 이진 스트림으로 씁니다 response.getOutputStream()
. 이렇게하는 것을 잊지 response.flush()
말에 그 그것을해야한다.
@RequestMapping(value = "/foo/bar", produces = "application/pdf")
Spring 3.0에서는 HttpEntity
return 객체를 사용할 수 있습니다 . 이것을 사용하면 컨트롤러에 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
) 다음은 현명하지 않을 것이다 NOT 먼저 바이트 배열 할 수 있습니다. 대신 다음을 사용하는 것이 좋습니다.
InputStreamResource
,PathResource
(Spring 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);
}
return new ResponseEntity<byte[]>(documentBody, headers, HttpStatus.CREATED)
ResponseEntity
에 HttpEntity
(그러나 나는 그것을 얻는) 서브 클래스는 201 CREATED는 데이터에 대한 뷰를 반환 할 때 사용할 것이 아닙니다. ( 201 CREATED에 대해서는 w3.org/Protocols/rfc2616/rfc2616-sec10.html 참조 )
만약 너라면:
byte[]
응답으로 보내기 전에 전체 파일을로드하기를 원하지 않습니다 .InputStream
.@ControllerAdvice
픽업 예외가 있거나 없습니다.아래 코드는 필요한 것입니다.
@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET)
public ResponseEntity<FileSystemResource> downloadStuff(@PathVariable int stuffId)
throws IOException {
String fullPath = stuffService.figureOutFileNameFor(stuffId);
File file = new File(fullPath);
long fileLength = file.length(); // this is ok, but see note below
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentType("application/pdf");
respHeaders.setContentLength(fileLength);
respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf");
return new ResponseEntity<FileSystemResource>(
new FileSystemResource(file), respHeaders, HttpStatus.OK
);
}
파일 길이 부분에 관해서 : File#length()
일반적인 경우에는 충분해야하지만 , 느릴 수 있기 때문에이 관찰을 할 것이라고 생각했습니다. 이 경우 이전에 저장해야합니다 (예 : DB). 파일이 큰 경우, 특히 파일이 원격 시스템에 있거나 그와 같이 좀 더 정교한 경우 (데이터베이스 등)에는 느릴 수 있습니다.
InputStreamResource
리소스가 파일이 아닌 경우 (예 : DB에서 데이터를 선택하는 경우)를 사용해야합니다 InputStreamResource
. 예:
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
FileSystemResource
거기 에서 사용하는 것이 좋다고 생각합니다 . 리소스가 파일 인 경우 에도 권장 됩니다 . 이 샘플에서는 FileSystemResource
어디에서나 사용할 수 있습니다 InputStreamResource
.
File#length()
일반적인 경우에 충분해야합니다. 파일이 원격 시스템에 있거나 데이터베이스와 같은 정교한 파일 인 경우 특히 느릴 수 있기 때문에 방금 언급했습니다. 그러나 이전이 아니라 문제가되는 경우 (또는 확실한 증거가있는 경우)에만 걱정하십시오. 요점은 : 파일을 스트리밍하기 위해 노력하고 있습니다. 파일을 모두 미리로드해야한다면 스트리밍에 아무런 차이가 없습니다.
이 코드는 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 / <RANDOM-FILENAME> .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")
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());
}
}
아래와 같은 것
@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를 표시하거나 예제를 다운로드 할 수 있습니다
유용한 답변이 될 수 있습니다.
프론트 엔드에서 데이터를 pdf 형식으로 내보내도 되나요?
이를 확장하여 컨텐츠 처리를 첨부 파일 (기본값)로 추가하면 파일이 다운로드됩니다. 보고 싶다면 인라인으로 설정해야합니다.
필자의 경우 요청에 따라 파일을 생성하므로 URL도 생성해야합니다.
나를 위해 다음과 같이 작동합니다.
@RequestMapping(value = "/files/{filename:.+}", method = RequestMethod.GET, produces = "text/csv")
@ResponseBody
public FileSystemResource getFile(@PathVariable String filename) {
String path = dataProvider.getFullPath(filename);
return new FileSystemResource(new File(path));
}
MIME 형식이 매우 중요 produces
하며 파일 이름이 링크의 일부이므로를 사용해야 @PathVariable
합니다.
HTML 코드는 다음과 같습니다.
<a th:href="@{|/dbreport/files/${file_name}|}">Download</a>
여기서 ${file_name}
컨트롤러의 Thymeleaf에 의해 생성되고 result_20200225.csv이므로 전체 URL behing 링크는 다음과 같습니다 example.com/aplication/dbreport/files/result_20200225.csv
.
링크 브라우저를 클릭하면 파일로 무엇을 할 것인지 묻습니다-저장 또는 열기.