axios同一个接口,同时接收 文件 或者 数据

1、前端代码

javascript 复制代码
const service = axios.create({
  baseURL: "http://192.168.2.200:8080/api",
  timeout: 180000
})

// 响应拦截
service.interceptors.response.use(async response => {
  if(response){
    // 请求时设置返回blob, 但是实际上可能返回的是json的情况
    if (response.data instanceof Blob) {
      if (!response.headers['content-type']?.includes('application/json')) {
        let a = document.createElement("a");
        a.setAttribute("href", URL.createObjectURL(response.data));
        a.setAttribute("download", decodeURI(response.headers['filename']));
        a.setAttribute("target", "_blank");
        a.click()
        return null
      }
      // 将后台返回的内容转成文本
      response.data = JSON.parse(await (response.data).text())
    }
  return response.data
}, err)

主要是:**if (response.data instanceof Blob)**判断是否是 Blob 对象,

否则使用:**response.data = JSON.parse(await (response.data).text())**将后台返回的内容转成 文本 返回

javascript 复制代码
const formData = new FormData();
formData.append('id', 1);
formData.append('file', _file.file);

const config = {
    headers: { 'Content-Type': 'multipart/form-data' },
    responseType: 'blob'
}

axios.post('/file/upload', formData, config).then((res: any) => {
          if (res != null && res.code == 200) {
             alert("上传成功");
          } else {
            alert("上传失败");
          }
        })

主要是:responseType: 'blob'

2、后端代码

java 复制代码
@Controller
@RequestMapping("api/file")
public class FileController {


    @PostMapping("upload")
    public void upload(MultipartFile file, HttpServletResponse response) {

        // 缓存文件
        String tmpDirPath = FileUtil.getTmpDirPath();
        // 上传文件名
        String originalFilename = file.getOriginalFilename();
        String targetFile = tmpDirPath + File.separator + originalFilename;
        FileUtil.writeFromStream(file.getInputStream(), targetFile);

        // 解析文件
        boolean result = parseFile(targetFile);
        if(!result){
            // 解析失败,返回失败文件
            InputStream in = new FileInputStream(targetFile);
            String filename = "解析失败_" + System.currentTimeMillis() + "_" + originalFilename;

            // 告诉浏览器输出内容为流
            response.setContentType("application/octet-stream;charset=utf-8");
            // 前端下载时的文件名
            response.setHeader("filename", URLEncoder.encode(filename, "UTF-8"));
            // 响应报头 指示哪些报头可以 公开 为通过列出他们的名字的响应的一部分。要公开多个自定义标题,可以用逗号分隔
            // 默认情况下,只显示6个简单的响应头 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
            response.setHeader("Access-Control-Expose-Headers", "filename");
            IOUtils.copy(in, response.getOutputStream());

         } else {
            response.setContentType("application/json;charset=utf-8");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 200);
            jsonObject.put("message", "成功");
            response.getWriter().write(jsonObject.toJSONString());
         }

        // 删除临时文件
        FileUtil.del(targetFile);

    }

}

需要注意的是:response.setHeader("Access-Control-Expose-Headers", "filename");

否则前端读取不到 **response.headers['filename']**的值

相关推荐
努力努力再努力wz几秒前
【C++高阶系列】告别内查找局限:基于磁盘 I/O 视角的 B 树深度剖析与 C++ 泛型实现!(附B树实现源码)
java·linux·开发语言·数据结构·c++·b树·算法
hero.fei2 分钟前
RoaringBitmap在SpringBoot中的使用以及与BitSet对比
java·spring boot·spring
Traving Yu4 分钟前
Spring源码与框架原理
java·后端·spring
freeWayWalker4 分钟前
Vue通用缩放容器
前端·javascript·vue.js
Lyyaoo.8 分钟前
【JAVA基础面经】线程安全的单例模式
java·安全·单例模式
AI服务老曹9 分钟前
异构计算与边缘协同:基于 Spring Boot 的 AI 视频管理平台架构深度解析
人工智能·spring boot·音视频
Hello--_--World11 分钟前
VUE:逻辑复用
前端·javascript·vue.js
_李小白13 分钟前
【OSG学习笔记】Day 39: NodeCallback(帧回调机制)
java·笔记·学习
如来神掌十八式15 分钟前
设计模式之装饰器模式
java·设计模式
好大哥呀16 分钟前
如何在Spring Boot中配置数据库连接?
数据库·spring boot·后端