Java 使用 FileSystemResource 强制下载文件时如何设置“Content-Disposition”和“Filename”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16601428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set 'Content-Disposition' and 'Filename' when using FileSystemResource to force a file download file?
提问by Hassan Jamil
What is the most appropriate, and standard, way to set the Content-Disposition=attachment
and filename=xyz.zip
using Spring 3 FileSystemResource
?
设置Content-Disposition=attachment
和filename=xyz.zip
使用 Spring 3的最合适、最标准的方法是FileSystemResource
什么?
The action looks like :
动作如下:
@ResponseBody
@RequestMapping(value = "/action/{abcd}/{efgh}", method = RequestMethod.GET, produces = "application/zip")
@PreAuthorize("@authorizationService.authorizeMethod()")
public FileSystemResource doAction(@PathVariable String abcd, @PathVariable String efgh) {
File zipFile = service.getFile(abcd, efgh);
return new FileSystemResource(zipFile);
}
Although the file is a zip file so the browser always downloads the file, but I would like to explicitly mention the file as attachment, and also provide a filename that has nothing to do with the files actual name.
虽然该文件是 zip 文件,因此浏览器始终会下载该文件,但我想明确提及该文件作为附件,并提供一个与文件实际名称无关的文件名。
There might be workarounds for this problem, but I would like to know the proper Spring and FileSystemResource
way to achieve this goal.
这个问题可能有解决方法,但我想知道正确的 Spring 和FileSystemResource
实现这个目标的方法。
P.S. The file that is being used here is a temporary file, marked for deletion when the JVM exists.
PS这里使用的文件是临时文件,JVM存在时标记为删除。
采纳答案by Hassan Jamil
@RequestMapping(value = "/action/{abcd}/{efgh}", method = RequestMethod.GET)
@PreAuthorize("@authorizationService.authorizeMethod(#id)")
public HttpEntity<byte[]> doAction(@PathVariable ObjectType obj, @PathVariable Date date, HttpServletResponse response) throws IOException {
ZipFileType zipFile = service.getFile(obj1.getId(), date);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
response.setHeader("Content-Disposition", "attachment; filename=" + zipFile.getFileName());
return new HttpEntity<byte[]>(zipFile.getByteArray(), headers);
}
回答by Kumar
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
@ResponseBody
public FileSystemResource getFile(@PathVariable("file_name") String fileName,HttpServletResponse response) {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=somefile.pdf");
return new FileSystemResource(new File("file full path"));
}
回答by vallismortis
Here is an alternative approach for Spring 4. Note that this example clearly does not use good practices regarding filesystem access, this is just to demonstrate how some properties can be set declaratively.
这是 Spring 4 的另一种方法。请注意,此示例显然没有使用有关文件系统访问的良好实践,这只是为了演示如何以声明方式设置某些属性。
@RequestMapping(value = "/{resourceIdentifier}", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
// @ResponseBody // Needed for @Controller but not for @RestController.
public ResponseEntity<InputStreamResource> download(@PathVariable(name = "resourceIdentifier") final String filename) throws Exception
{
final String resourceName = filename + ".dat";
final File iFile = new File("/some/folder", resourceName);
final long resourceLength = iFile.length();
final long lastModified = iFile.lastModified();
final InputStream resource = new FileInputStream(iFile);
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=" + resourceName)
.contentLength(resourceLength)
.lastModified(lastModified)
.contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE)
.body(resource);
}
回答by Fahad Alkamli
Made few changes to both given answers and I ended up with the best of both in my project where I needed to extract an image from the database as a blob and then serve it to the clients :
对两个给出的答案都做了很少的更改,我最终在我的项目中获得了两者中最好的结果,我需要从数据库中提取图像作为 blob,然后将其提供给客户端:
@GetMapping("/images/{imageId:.+}")
@ResponseBody
public ResponseEntity<FileSystemResource> serveFile(@PathVariable @Valid String imageId,HttpServletResponse response)
{
ImageEntity singleImageInfo=db.storage.StorageService.getImage(imageId);
if(singleImageInfo==null)
{
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
Blob image=singleImageInfo.getImage();
try {
String filename= UsersExtra.GenerateSession()+"xxyy"+singleImageInfo.getImage1Ext().trim();
byte [] array = image.getBytes( 1, ( int ) image.length() );
File file = File.createTempFile(UsersExtra.GenerateSession()+"xxyy", singleImageInfo.getImage1Ext().trim(), new File("."));
FileOutputStream out = new FileOutputStream( file );
out.write( array );
out.close();
FileSystemResource testing=new FileSystemResource(file);
String mimeType = "image/"+singleImageInfo.getImage1Ext().trim().toLowerCase().replace(".", "");
response.setContentType(mimeType);
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", filename);
response.setHeader(headerKey, headerValue);
// return new FileSystemResource(file);
return ResponseEntity.status(HttpStatus.OK).body( new FileSystemResource(file));
}catch(Exception e)
{
System.out.println(e.getMessage());
}
return null;
}
Using a ResponseEntity in Kumar's code will help you respond with the correct Response code. Note: converting from a blob to a file is quoted from this link: Snippet to create a file from the contents of a blob in Java
在 Kumar 的代码中使用 ResponseEntity 将帮助您使用正确的响应代码进行响应。注意:从 blob 到文件的转换引用自以下链接: Snippet to create a file from a blob in Java
回答by Jefferson Lima
In addition to the accepted answer, Spring has the class ContentDispositionspecific for this purpose. I believe it deals with the file name sanitization.
除了已接受的答案之外,Spring 还具有专门用于此目的的ContentDisposition类。我相信它涉及文件名清理。
ContentDisposition contentDisposition = ContentDisposition.builder("inline")
.filename("Filename")
.build();
HttpHeaders headers = new HttpHeaders();
headers.setContentDisposition(contentDisposition);