【问题标题】:How to set 'Content-Disposition' and 'Filename' when using FileSystemResource to force a file download file?使用 FileSystemResource 强制下载文件时如何设置“Content-Disposition”和“Filename”?
【发布时间】:2013-05-12 04:08:11
【问题描述】:

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

动作看起来像:

@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存在时标记为删除。

【问题讨论】:

    标签: java spring spring-3 content-disposition


    【解决方案1】:
    @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);
    }
    

    【讨论】:

    • 但请注意,如果文件名包含非“标记”字符,例如空格、非 ASCII 和某些分隔符,则会中断。
    • 简答response.setHeader("Content-Disposition", "attachment; filename=" + YOUR_FILE_NAME);
    • 避免纯代码答案。提供一些关于sn-p的解释!
    • 把文件名放在双引号"之间。
    • 当心,如果文件名没有得到适当的清理,这个解决方案可能会导致一个简单的跨站点脚本攻击!
    【解决方案2】:
     @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")); 
        }
    

    【讨论】:

    • 这个方法到底返回了什么? myService 是什么?
    • @user3809938 FileSystemResource 的构造函数可以采用FileString 作为路径
    【解决方案3】:

    这是 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);
    }
    

    【讨论】:

      【解决方案4】:

      对两个给定的答案都做了一些更改,最终我在我的项目中得到了最好的结果,我需要从数据库中提取图像作为 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;
      }
      

      在 Kumar 的代码中使用 ResponseEntity 将帮助您使用正确的响应代码进行响应。 注意:从 blob 转换为文件引用自此链接: Snippet to create a file from the contents of a blob in Java

      【讨论】:

        【解决方案5】:

        除了已接受的答案之外,Spring 还具有专门用于此目的的 ContentDisposition 类。我相信它处理文件名清理。

              ContentDisposition contentDisposition = ContentDisposition.builder("inline")
                  .filename("Filename")
                  .build();
        
              HttpHeaders headers = new HttpHeaders();
              headers.setContentDisposition(contentDisposition);
        

        【讨论】:

        • 有趣的是,直到最近,ContentDisposition 类仅在将字符集指定为非 US-ASCII 时才对文件名进行编码:github.com/spring-projects/spring-framework/issues/24220
        • 如果您必须使用他们的构建器构建HttpServletResponseResponseEntity,您仍然可以使用ContentDisposition 类为您生成标题字符串:response.setHeader(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString()); 它会小心的转义必要的字符。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-18
        • 2016-08-25
        • 1970-01-01
        • 2013-10-15
        • 1970-01-01
        相关资源
        最近更新 更多