vue 向后台请求 blob 数据报 net::ERR_FAILED 错误?

场景描述:

webpack 代理设置

proxyTable: {
  '/api': {
    target: 'http://localhost:80/',
    changeOrigin: true, 
    pathRewrite: {
      '^/api': '/'
    }
  }
},

api接口

// 下载资源
export function downloadCourseResource(url) {
  return Axios({
    url: url,
    method: 'get',
    responseType: 'blob'
  })
}

下载函数

onDownload(resource) {
  downloadCourseResource(resource.url)
    .then(res => {
      const blob = res.data.blob
      const oname = res.data.originalName
      const expName = oname.substr(oname.lastIndexOf('.'))
      const a = document.createElement('a')
      const objectUrl = window.URL.createObjectURL(blob)
      a.download = resource.name + expName
      a.href = objectUrl
      a.click()
      window.URL.revokeObjectURL(objectUrl)
    }).catch(err => {
      this.$message.error(err)
    })
},

axios 配置

const Axios = axios.create({
  baseURL: '/api',
  timeout: 60000,
  responseType: 'json',
  withCredentials: true
})

const requestList = new Set() // 存储请求url
Axios.requestList = requestList // 挂在到全局

Axios.interceptors.response.use(function(response) {
  // 请求不能在 600 内重复发送
  setTimeout(() => {
    requestList.delete(response.config.url)
  }, 600)

  // data 是 Blob 说明是请求资源文件
  if (response.data instanceof Blob) {
    const res = {}
    res.code = global.successResponseCode
    const data = {}
    const url = response.config.url
    const originalName = url.substr(url.lastIndexOf('/') + 1)
    data.originalName = originalName
    data.blob = response.data
    res.data = data
    return res
  },
  error => {
  // 处理非 2xx 响应
  if (axios.isCancel(error)) {
    // 请求取消
    console.warn(error)
    return
  }
  console.log('响应拦截器发生异常')
  if (error.code === 'ERR_NETWORK') {
    return Promise.reject('网络异常')
  }
  if (error.response.status === 504) {
    return Promise.reject('无法连接到服务器')
  }
  return Promise.reject(error.message)
})

// axios 请求拦截器 -- 防止重复请求
axios.interceptors.request.use(function(config) {
config.cancelToken = new axios.CancelToken(e => {
  requestList.has(config.url) ? e(`${location.host}${config.url}---重复请求被中断`) : requestList.add(config.url)
})
return config
}, error => {
return Promise.reject(error)
})

控制台输出
image.png

问题描述:

我无法下载文件,一直报错,之前是可以的,看网上很多都说是代理的问题,但是我其他接口都没有问题,只有这个有问题,而且只要去掉 responseType: 'blob' 就不会报这个错误

请教大家该如何解决orz

补充实验:

最近浏览器装了新的插件,我怀疑是插件的原因,于是我把插件关了还是不行
我到chrom浏览器尝试了一下,正常下载(期间有一次也报了网络错误)
我又到edge private 模式下尝试,正常下载
于是我重启浏览器,发现ppt文件可以下载,我猜测是mp4文件的问题
后来发现视频资源一是可以下载的,但是视频资源二一直报网络错误
我看了下视频资源的大小,视频资源二是视频资源一的十倍,猜测可能是这个原因

image.png

阅读 4.4k
2 个回答

看请求的URL直接是视频文件,并不是文件流,所以你用 responseType: 'blob' 会报错。
直接把URL放到 <a> 标签的 href 属性内就行了。

写了段最简单的测试代码,测试一下没有问题,可以下载到mp4文件,
你的问题 我估计还是给过代理以后,mp4文件的位置不正确
你试试把下面你的URL直接通过浏览器访问是否可以

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  
</head>
<body>
<script type="text/javascript">
    axios.get('http://127.0.0.1/123.mp4', {
                responseType: 'blob' //返回数据的格式,可选值为arraybuffer,blob,document,json,text,stream,默认值为json
            })
            .then(response => {
                console.log(response);
                let url = window.URL.createObjectURL(response.data);
                console.log(url)
                var a = document.createElement("a");
                document.body.appendChild(a);
                a.href = url;
                        a.download = '2.mp4';
                        a.click();
                        window.URL.revokeObjectURL(url);
            })
            .catch(err => {
                console.log(`接口调用失败`);
               
                console.log(err);
            })

</script>
</body>
</html>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题