Кажется, что это ошибка после обновления зависимостей gradle до 24+. Проверьте этот ответ. Перед этим все мои setError()
работали нормально. Кроме того, вы не должны требовать фокуса, чтобы отобразить ошибку.
@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");
Если вы:
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
.
FileSystemResource
. Даже рекомендуется , если ваш ресурс является файлом i>. В этом примере FileSystemResource
можно использовать, где InputStreamResource
.
– acdcjunior
27 April 2015 в 15:35
File#length()
должно быть достаточно хорошим в общем случае. Я просто упомянул об этом, потому что он может быть медленным , особенно если файл находится в удаленной системе или что-то более разработанное - база данных, может быть ?. Но только беспокоитесь, если это станет проблемой (или если у вас есть убедительные доказательства, она станет одной), а не раньше. Главное: вы пытаетесь передать файл, если вам нужно предварительно загрузить все это раньше, тогда потоковая передача не имеет никакого значения, а?
– acdcjunior
13 May 2015 в 15:21
С 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
), тогда было бы разумно НЕ сделать это байтовым массивом в первую очередь. Вместо этого лучше использовать:
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)
– Amr Mostafa
8 October 2014 в 12:16
ResponseEntity
является подклассом HttpEntity
(но я его получаю), с другой стороны, 201 CREATED - это не то, что я буду использовать, когда вернусь только к представлению данных. (см. w3.org/Protocols/rfc2616/rfc2616-sec10.html для 201 СОЗДАНО)
– Ralph
8 October 2014 в 13:39
То, что я могу быстро подумать, - создать pdf-файл и сохранить его в webapp / downloads / & lt; 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";
Этот код отлично работает, чтобы автоматически загрузить файл с контроллера Spring при нажатии ссылки на 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();
}
}
Мне удалось передать эту строку, используя встроенную поддержку весной с помощью 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
таким образом?
– Ralph
15 April 2015 в 12:54
Ниже код работал для меня для создания и загрузки текстового файла.
@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);
}
что-то вроде ниже
@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 или загрузить его примеры здесь
Вы должны иметь возможность напрямую записывать файл в ответ. Что-то вроде
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\"");
, а затем напишите файл как двоичный поток на response.getOutputStream()
. Не забудьте сделать response.flush()
в конце, и это должно сделать это.
@RequestMapping(value = "/foo/bar", produces = "application/pdf")
– Black
7 May 2014 в 06:44
IOUtils
вместо SpringFileCopyUtils
? – Powerlord 18 September 2012 в 17:12