【问题标题】:Can Spring Boot set the name of a file being downloaded from a controller endpoint?Spring Boot 可以设置从控制器端点下载的文件的名称吗?
【发布时间】:2022-01-13 16:55:54
【问题描述】:

Java 11 和 Spring Boot 2.5.x 在这里。我知道我可以设置一个控制器来返回文件的内容,如下所示:

@GetMapping(
  value = "/get-image-with-media-type",
  produces = MediaType.IMAGE_JPEG_VALUE
)
public @ResponseBody byte[] getImageWithMediaType() throws IOException {
    InputStream in = getClass()
      .getResourceAsStream("/path/to/some/image.jpg");
    return IOUtils.toByteArray(in);
}

但是如果我想控制发回的文件的名称怎么办?例如,在服务器端,文件名可能存储为“image.jpg”,但我想将其返回为“<userId>-<YYYY-mm-DD>-image.jpg”,其中<userId> 是用户 ID提出请求的经过身份验证的用户,<YYYY-mm-DD> 是提出请求的日期?

例如,如果用户 123 在 2021 年 12 月 10 日提出请求,则文件将下载为“123-2021-12-10-image.jpg”,如果用户 234 提出2022 年 1 月 17 日的请求将被下载为“234-2022-01-17-image.jpg”。这是否可以在 Spring/Java/服务器端进行控制,还是由 HTTP 客户端(浏览器、PostMan 等)来决定文件名?

【问题讨论】:

标签: java spring-boot model-view-controller multipartfile


【解决方案1】:

请试试这个,cmets inline:

package com.example;

import java.io.IOException;
import java.security.Principal;
import java.util.Date;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;


@Controller
public class SomeController {

  @GetMapping(
      value = "/get-image-with-media-type",
      produces = MediaType.IMAGE_JPEG_VALUE
  ) // we can inject user like this (can be null, when not secured):
  public ResponseEntity<byte[]> getImageWithMediaType(Principal user) throws IOException {
    // XXXResource is the "spring way", FileSystem- alternatively: ClassPath-, ServletContext-, ...
    FileSystemResource fsr = new FileSystemResource("/path/to/some/image.jpg");
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION,
        // for direct downlad "inline", for "save as" dialog "attachment" (browser dependent)
        // filename placeholders: %1$s: user id string, 2$tY: year 4 digits, 2$tm: month 2 digits, %2$td day of month 2 digits
        String.format("inline; filename=\"%1$s-%2$tY-%2$tm-%2$td-image.jpg\"",
            // user name, current (server) date:
            user == null ? "anonymous" : user.getName(), new Date()));

    // and fire:
    return new ResponseEntity<>(
        IOUtils.toByteArray(fsr.getInputStream()),
        responseHeaders,
        HttpStatus.OK
    );
  }
}

相关参考:

使用ContentDisposition,它可以看起来(只是)像:

responseHeaders.setContentDisposition(
  ContentDisposition
    .inline()// or .attachment()
    .filename(// format file name:
      String.format(
        "%1$s-%2$tY-%2$tm-%2$td-image.jpg",
        user == null ? "anonymous" : user.getName(),
        new Date()
      )
    )
    .build()
);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 2018-01-22
    • 2020-01-18
    • 2019-01-02
    • 2019-10-26
    • 1970-01-01
    • 2020-08-06
    相关资源
    最近更新 更多