关于java:使用FileSystemResource强制文件下载文件时,如何设置“ Content-Disposition”和“ Filename”?

How to set 'Content-Disposition' and 'Filename' when using FileSystemResource to force a file download file?

使用Spring 3 FileSystemResource设置Content-Disposition=attachmentfilename=xyz.zip的最合适,最标准的方法是什么?

动作看起来像:

1
2
3
4
5
6
7
8
9
@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);
}

尽管该文件是zip文件,所以浏览器始终会下载该文件,但是我想明确提及该文件作为附件,并且还提供与该文件的实际名称无关的文件名。

可能有解决此问题的方法,但我想知道实现此目标的正确Spring和FileSystemResource方法。

附言 此处使用的文件是一个临时文件,当JVM存在时,标记为删除。


1
2
3
4
5
6
7
8
9
10
11
@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);
}


除了可接受的答案外,Spring还具有为此目的而特定的类ContentDisposition。 我相信它可以处理文件名清理。

1
2
3
4
5
6
      ContentDisposition contentDisposition = ContentDisposition.builder("inline")
          .filename("Filename")
          .build();

      HttpHeaders headers = new HttpHeaders();
      headers.setContentDisposition(contentDisposition);


1
2
3
4
5
6
7
 @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"));
    }


这是Spring 4的另一种方法。请注意,此示例显然未使用有关文件系统访问的良好做法,这只是为了演示如何声明性地设置某些属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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);
}

对给定的答案进行了很少的更改,最后我在项目中取得了两者的最佳,我需要从数据库中提取图像作为Blob,然后将其提供给客户:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@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;
}

在Kumar的代码中使用ResponseEntity将帮助您使用正确的Response代码进行响应。
注意:此链接引用了从Blob到文件的转换:
通过Java中的Blob内容创建文件的代码段