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

Axios Get请求无法接收数据:S3桶内容下载接口返回空对象问题排查

问题分析

你遇到的核心问题是Controller层返回值类型不正确,导致Spring无法正确处理响应输出,进而前端(Postman/浏览器)接收到空对象——而IntelliJ控制台看到的只是服务端本地打印的流对象信息,并非实际返回给前端的有效数据。

当你直接返回ByteArrayOutputStream时,Spring MVC默认会尝试把它当作普通Java对象进行序列化(比如转成JSON),但这个类没有可被序列化的有效业务字段,所以最终返回给前端的就是空对象{}。

解决方案

我们需要修改Controller来返回标准的HTTP响应(包含二进制数据和正确的响应头),同时调整Axios请求逻辑来处理二进制数据流。

1. 修改Controller层代码

把返回值改成ResponseEntity<Resource>,这样可以明确指定响应的内容类型、文件名等信息,Spring会正确输出二进制数据:

import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;

@GetMapping(value = "downloadSearchData") 
public ResponseEntity<Resource> downloadSearchData() throws IOException { 
    ByteArrayOutputStream out = targetLocationService.downloadSearchData();
    // 将字节流转换为Spring可识别的资源类型
    ByteArrayResource resource = new ByteArrayResource(out.toByteArray());
    
    // 设置响应头,指定下载文件名和内容类型
    HttpHeaders headers = new HttpHeaders();
    headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"7863784198_2021-08-16T13_30_06.690Z.json\"");
    
    return ResponseEntity.ok()
            .headers(headers)
            .contentLength(resource.contentLength())
            .contentType(MediaType.APPLICATION_JSON) // 因为文件是JSON类型,也可以用通用二进制类型APPLICATION_OCTET_STREAM
            .body(resource);
}

2. 调整Axios请求代码

现在接口返回的是二进制数据流,需要告诉Axios以blob格式接收响应,才能正确处理并生成可下载的文件:

downloadLocations() { 
  axios.get("http://localhost:8080/api/v1/targetLocation/downloadSearchData", {
    responseType: 'blob' // 关键:指定响应类型为blob,否则会解析成错误的JSON
  }) 
  .then((res) => { 
    console.log(res.data); // 现在会拿到Blob对象
    // 从响应头中提取文件名(和Controller设置的对应)
    const fileName = res.headers['content-disposition'].split('filename="')[1].split('"')[0];
    // 创建下载链接并触发下载
    const url = window.URL.createObjectURL(res.data);
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', fileName);
    document.body.appendChild(link);
    link.click();
    // 清理临时资源
    window.URL.revokeObjectURL(url);
    document.body.removeChild(link);
  }, (error) => { 
    console.error(error); 
  }); 
}

3. Service层代码无需修改

你的Service层从S3获取文件并写入ByteArrayOutputStream的逻辑是正确的,这个部分可以保持原样。

补充说明:为什么IntelliJ控制台能看到输出?

你在Service层打印的System.out.println(out);只是输出了ByteArrayOutputStream对象的内存地址(类似java.io.ByteArrayOutputStream@xxxxxx),并不是实际的文件内容,这和返回给前端的响应没有任何关系。

内容的提问来源于stack exchange,提问作者Tip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 05:12:49