回答:
@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タイプを判別できる場合、これは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));
}
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フレームワークの戻り値がバイト配列の場合(他の戻り値については私の回答の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フレームワークの戻り値の型(documentBbody
)がまだバイト配列ではない(そしてもないByteArrayInputStream
)場合は、最初にバイト配列にしない方が賢明です。代わりに、それを使用することをお勧めします:
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のリンクをクリックすると、Spring Controllerから自動的にファイルをダウンロードするように機能します。
@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形式でデータをエクスポートしても問題ありませんか?
これに拡張して、content-dispositionを添付ファイルとして追加すると(デフォルト)、ファイルがダウンロードされます。表示したい場合は、インラインに設定する必要があります。
私の場合、オンデマンドでファイルを生成しているため、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は次のようになりexample.com/aplication/dbreport/files/result_20200225.csv
ます。
リンクブラウザーをクリックした後、ファイルをどうするかを尋ねられます-保存または開く。