vue3 POST请求中,文件流下载添加responseType: ‘arraybuffer‘的问题

问题:

let data = { fileId: 'sddfsfsfds' }
const res = await axios({
    method: 'POST',
    url: 'https://xxxxxxx/xxxxx',
    data,
    responseType: 'arraybuffer'
}) 
改写成 const res = await proxy.$httpPost('url', xxxxx, ....  的方式

解决:

假设你有一个封装了 Axios 请求的代理对象 proxy,其中 $httpPost 是一个方法,用于发送 POST 请求。你需要将原始的 Axios 请求改写为使用这个代理对象的方法。

以下是如何将原始的 Axios 请求改写为使用 proxy.$httpPost 方法的示例:

import { ref, reactive } from 'vue';
import { useProxy } from 'path-to-your-proxy-module'; // 假设你有一个代理模块

export default {
  setup() {
    const proxy = useProxy(); // 获取代理对象
    const data = reactive({ fileId: 'sddfsfsfds' }); // 使用reactive来使data响应式
    const res = ref(null); // 用于存储响应结果

    async function fetchData() {
      try {
        res.value = await proxy.$httpPost('https://xxxxxxx/xxxxx', data, {
          responseType: 'arraybuffer' // 确保将响应类型设置为arraybuffer
        });
      } catch (error) {
        console.error('请求失败:', error);
      }
    }

    // 调用fetchData函数
    fetchData();

    return {
      res,
      fetchData
    };
  }
};

在这个组件中:

  • 使用 reactive 来定义响应式的数据对象 data
  • 使用 ref 来定义响应式的结果变量 res
  • 定义了一个异步函数 fetchData 来处理 HTTP 请求。
  • 使用 await 等待 proxy.$httpPost 方法的响应。
  • 使用 try...catch 结构来处理可能发生的错误。

请注意,这里的 useProxyproxy.$httpPost 是假设的,你需要根据你的项目实际情况来调整。确保 $httpPost 方法接受正确的参数,并且能够处理响应类型。

此外,res.value 用于存储请求返回的数据,你可以在模板或其他计算属性中使用它。最后,你可以在组件的适当位置调用 fetchData 函数,例如在组件的生命周期钩子中,或者在用户触发的事件处理函数中。

 遇到的另外一个问题:

如果responseType的值改为'blob',responseType: 'blob' // 确保将响应类型设置为blob,会发现可以下载,但是打开不了。而用responseType: 'arraybuffer' 就可以。初步判断应该是后端返回的数据格式问题,但是后端还没注意到这个点。

文件流下载基本原理:

  1. 从服务器获取数据流。
  2. 将数据流转换成Blob对象。
  3. 创建一个URL指向该Blob对象。
  4. 创建一个a标签,设置其href属性为该URL,download属性为文件名。
  5. 模拟点击a标签,触发文件下载。
  6. 完成下载后,释放URL对象。

 实现过程也可以把下载函数封装成一个通用的方法:

/**
 * data: 下载文件
 * fileName: 文件名
 * type: 下载文件类型
 */
export function downloadHandler(data, fileName, type) {
  // 匹配任意文件类型:type : "application/octet-stream"
  const blob = new Blob([data], { type: type || 'application/octet-stream' });
  const downloadElement = document.createElement('a');
  const href = window.URL.createObjectURL(blob);
  downloadElement.href = href;
  downloadElement.download = fileName;
  document.body.appendChild(downloadElement);
  downloadElement.click();
  document.body.removeChild(downloadElement);
  window.URL.revokeObjectURL(href);
}

 这里只做一个参考,不一样的地方是传参,具体实现还要看实际需要。

// import axios from 'axios'
	 async function downloadFile(fileId) {
		 try {
			 // 错误传参方式:
			 // let params = { fileId: fileIds }
			 // cosnt res = await proxy.$httpGet('/xxxxxx/DownloadFileFromOss', { params, responseType: 'arraybuffer })
			 // cosnt res = await proxy.$httpGet('/xxxx/DownloadFileFromOss', { fileId: fileIds, responseType: 'arraybuffer })
			 // 上述写法错误

			 let data = { fileId: fileId }
			 let responseType = 'arraybuffer'
			 // const res = await axios({
			 //	method: 'POST',
			 // 	url: 'https://xxxxx/xxxxx/DownloadFileFromOss',
			 // 	data,
			 // 	responseType: 'arraybuffer'
			 // })	// 一开始用这种原生的写法可以下载打开,但是考虑到域名那些可能会改,改用下面方法,结合修改http/index.js文件的post方法封装

			 const res = await proxy.$httpPost('/xxxx/DownloadFileFromOss', data, responseType)
			 // console.log('res-download', res)
			 cosnt getNameRes = await proxy.$httpGet('/xxxxx/GetFileName', { fileId: fileIds })

			 if (res?.data) {
			     const data = res.data
			     const name = getNameRes.data

			     let blob = new Blob([data], { type: res.header['content-type'] || 'application/octet-stream' })		//  type: res.header['content-type']--使用获取的excel格式
			     const url = URL.createObjectURL(blob)
			     const alink = document.createElement('a')
			     alink.download = name
			     alink.style.display = 'none'
			     alink.href = url
			     document.body.appendChild(alink)
			     alink.click()						// 点击下载
			     URL.revokeObjectURL(alink.href)		// 释放掉blob对象
			     document.body.removeChild(alink)		// 下载完成移除元素
		     }
		   }catch(err) {
				 console.log('error', err.message)
		    }
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值