You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Java REST控制器实现S3链接重定向并保留下载文件名

问题根因

你写的Content-Disposition头没有生效,原因是这些头是附加在你服务端返回的301重定向响应上的。浏览器收到3xx重定向响应后,会直接跳转至Location指定的S3地址,此时浏览器只会使用S3返回的响应头,完全忽略重定向响应本身携带的Content-Disposition、Content-Type等头,所以你设置的文件名不会生效。

可行解决方案(无需代理下载文件,完全满足直接重定向的需求)

你不需要将文件下载到自有服务器再返回,只需要在生成S3访问链接的时候,主动指定S3返回响应的头参数即可,S3原生支持该能力:

  • 公开访问的S3对象:直接在访问链接后拼接response-content-disposition和response-content-type查询参数
  • 私有访问的S3对象:生成预签名URL时,直接指定这两个响应覆盖参数

代码修改示例(以AWS Java SDK v2为例)

你需要修改storageServiceS3.getUrl(uuid)的实现逻辑,加上响应头覆盖参数:

// 生成预签名URL时指定响应头
public String getUrl(UUID uuid, String fileName) {
    // 先编码文件名,防止中文、特殊字符出错
    String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
            .replace("+", "%20");
    String contentDisposition = "attachment; filename=\"" + encodedFileName + "\"";
    String contentType = new MimetypesFileTypeMap().getContentType(fileName);

    GetObjectRequest getObjectRequest = GetObjectRequest.builder()
            .bucket("你的桶名")
            .key(uuid.toString()) // 你存在S3上的key
            .responseContentDisposition(contentDisposition)
            .responseContentType(contentType)
            .build();

    GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
            .signatureDuration(Duration.ofMinutes(10)) // 链接有效期可自定义
            .getObjectRequest(getObjectRequest)
            .build();

    return presigner.presignGetObject(presignRequest).url().toString();
}

对应接口代码可以简化为:

@GetMapping("/test/{uuid}")
public ResponseEntity<Void> getFile(@PathVariable UUID uuid) {
    try {
        var name = storageServiceS3.getName(uuid);
        // 生成带响应头覆盖的S3链接
        var url = storageServiceS3.getUrl(uuid, name);
        return ResponseEntity.status(HttpStatus.FOUND) // 建议用302而不是301,防止浏览器缓存重定向规则后文件名更新不生效
                .header(HttpHeaders.LOCATION, url)
                .build();
    } catch (NoSuchKeyException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
    }
}

注意事项

  • 文件名包含中文、空格、特殊字符时必须做URL编码,否则会出现乱码
  • 如果你的S3是公开访问,不需要预签名,直接在原S3链接后拼接参数即可:{S3原链接}?response-content-disposition={编码后的disposition值}&response-content-type={编码后的contentType值}
  • 不建议使用301永久重定向,浏览器会长期缓存重定向规则,后续如果文件名调整可能不会生效,改用302临时重定向更合理

内容的提问来源于stack exchange,提问作者Алексеев станислав

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 19:24:00