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

本文介绍了如何在前端使用axios发送POST请求上传文件,以及后端JavaSpring如何处理文件上传、解析和响应头设置,确保跨域资源共享。

1、前端代码

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()) 将后台返回的内容转成 文本 返回

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、后端代码


@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'] 的值

### 使用 Axios 实现实时数据接收 要实现实时接收来自服务器的数据,通常会考虑使用 WebSocket 而不是传统的 HTTP 请求方式(如 `fetch` 或者 `axios`),因为后者本质上是非持续连接的。对于需要长时间保持连接并频繁交换少量数据的应用场景来说,WebSocket 是更合适的选择。 然而,在某些情况下也可以通过轮询的方式利用 `axios` 来模拟近似于实时的效果: #### 方法一:基于 WebSocket 的解决方案 如果项目允许的话,推荐采用 WebSocket 技术栈来构建双向通信机制。这不仅能够满足即时通讯的需求,而且相比起短时间间隔内的重复请求更加高效节能。下面是一个简单的 Vue 组件例子展示如何集成 WebSocket 和 ECharts 大屏以达到数据动态更新的目的[^1]: ```javascript // 建立 WebSocket 连接 const socket = new WebSocket('ws://yourserver.com/socket'); socket.onmessage = function(event) { const data = JSON.parse(event.data); // 更新图表数据逻辑... }; ``` 当收到新的消息时,解析其内容并将结果传递给视图层用于界面渲染或状态管理。 #### 方法二:HTTP 长轮询 (Long Polling) 另一种替代方案就是所谓的“长轮询”,即客户端发送一个普通的 AJAX 请求到服务器;但是不同于常规做法的是——一旦服务器端有了新信息就会立即响应这个请求而不是等到超时才返回。之后再由前端重新发起新一轮查询直到停止监听为止。这种方式虽然可以较好地兼容旧版浏览器环境,但在性能上不如原生支持 WebSockets 的现代平台表现得那么出色。 下面是使用 axios 库来进行长轮询的一个简单实例: ```typescript async function longPoll(url:string, callback:(data:any)=>void){ try{ let response = await axios.get(url); callback(response.data); // 如果一切正常则继续下一次轮询 setTimeout(() => {longPoll(url,callback)}, 0); }catch(error){ console.error("Error during polling:", error.message); // 出错重试策略可根据实际需求调整 setTimeout(() => {longPoll(url,callback)}, 5000); } } ``` 此函数接受两个参数:一个是目标 URL 地址字符串形式表示的目标 API 接口路径;另一个则是用来处理每次成功获取到的新鲜资讯所对应的回调函数对象。每当完成一轮交互操作后都会自动触发后续的任务调度流程直至显式终止条件达成之前一直循环往复下去。 考虑到题目提到的内容涉及到了文件传输进度监控,则可能更适合选用 WebSocket 方案以便更好地适应此类应用场景下的低延迟特性要求[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值