WebサイトからPDFをダウンロードする必要があるという要件があります。 PDFはコード内で生成する必要があります。これは、フリーマーカーとiTextのようなPDF生成フレームワークの組み合わせになると思いました。もっと良い方法は?
しかし、私の主な問題は、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");
}
}
一般的に言って、あなたがresponse.getOutputStream()
を持っているとき、あなたはそこに何か書くことができます。この出力ストリームをgenerated PDFをジェネレータに置く場所として渡すことができます。また、送信しているファイルの種類がわかっている場合は、次のように設定できます。
response.setContentType("application/pdf");
私はそれをResourceHttpMessageConverterでSpringに組み込まれたサポートを使用することによってこれを流すことができました。 MIMEタイプを決定できる場合、これは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()
をすることを忘れないでください、そしてそれはそれをするべきです。
Spring 3.0ではHttpEntity
returnオブジェクトを使うことができます。これを使うなら、あなたのコントローラはHttpServletResponse
オブジェクトを必要としないので、テストするのがより簡単です。 これを除いて、この答えはInfeligoのそれに相対的に等しいです。
あなたのpdfフレームワークの戻り値がバイト配列(他の戻り値については私の答えの2番目の部分を読んでください):の場合:
@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 Framework(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);
}
もし、あんたが:
byte[]
にロードしたくないです。InputStream
経由で送信/ダウンロードする必要があります。@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
のドキュメントをチェックしてください。
このコードはjsp上のリンクをクリックするとspringコントローラから自動的にファイルをダウンロードするのに問題なく動作しています。
@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", 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を表示するか、またはダウンロードしてくださいexample ここ
次の解決策は私のために働く
@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());
}
}
それが誰にでも役立つなら。あなたはInfeligoによって受け入れられた答えが示唆したことをすることができますが、ただ強制ダウンロードのためにコードにこの余分なビットを入れるだけです。
response.setContentType("application/force-download");