实现方式

  1. 在axios请求中注明responseType: 'blob',headers的Accept: 'audio/wav'不清楚要不要写,我加上了(请求接口)

  2. 在接口返回值中,使用Blob的构造方法将数据转换成Blob对象 (封装Blob对象&形成URL)

  3. 将得到的Blob对象通过URL.createObjectURL(audioBlob)形成url,该url类似于blob:http://localhost/2e29f7cf-51bf-4dec-9ced-1485ef128735复制该url到地址栏可以播放,但是该url只能本地播放,实际媒体文件存在内存里,一旦资源被释放,该url就无效了

请求接口

export function getAudioData(param) {
const url = `/api`
return request({
url: url,
responseType: 'blob', // 向axios注明该请求类型为blob,否则默认为json
headers: {
isToken: true,
Accept: 'audio/wav' // 不知道这个起作用了没有
},
method: 'get'
})
}

封装Blob对象&形成URL

getAudioData(val.id).then(res => {
const audioBlob = new Blob([res], { type: 'audio/wav' }) // 这按照自己的数据类型来写type的内容
const audioUrl = URL.createObjectURL(audioBlob) // 生成url
})

附:axios 封装

采用ruoyi-vue的默认封装,未修改其内容

import axios from 'axios'
import { Notification, MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver' let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = { show: false }; axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000
}) // request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
}, error => {
console.log(error)
Promise.reject(error)
}) // 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
store.dispatch('LogOut').then(() => {
location.href = '/index';
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
Message({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
Message({ message: msg, type: 'warning' })
return Promise.reject('error')
} else if (code !== 200) {
Notification.error({ title: msg })
return Promise.reject('error')
} else {
return res.data
}
},
error => {
console.log('err' + error)
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
} else if (message.includes("timeout")) {
message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
Message({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
) // 通用下载方法
export function download(url, params, filename, config) {
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
return service.post(url, params, {
transformRequest: [(params) => { return tansParams(params) }],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
...config
}).then(async (data) => {
const isLogin = await blobValidate(data);
if (isLogin) {
const blob = new Blob([data])
saveAs(blob, filename)
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
Message.error(errMsg);
}
downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
Message.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
})
} export default service

ruoyi-vue axios通过接口请求wav、mp3音频二进制数据的更多相关文章

  1. axios取消接口请求

    axios取消请求 这里就是分析一下接口请求需要被取消时的一些操作 因为我是用vue写的项目,所以标配用的是axios,怎么在axios中取消已经发送的请求呢? 1.在这之前我们还是先介绍一下原生js ...

  2. vue axios配置 发起请求加载loading请求结束关闭loading

    axios带有请求拦截器,避免在每个请求里面加loading重复操作,可以封装进去,在请求开始时加载loading层,请求结束关闭,loading层用vux的loading加载 axios.js im ...

  3. vue+axios 对restful 请求封装

    礼拜天来公司整理项目,项目是最近开始重构的,里面的各种http请求接口是restful结构的(为了提升项目的比格),整理一下笔记 [restful介绍][1]博主讲的很详细 技术栈: vue + vu ...

  4. vue axios 取消上次请求

    axios.defaults.timeout = 1000 * 5axios.defaults.baseURL = baseUrlvar CancelToken = axios.CancelToken ...

  5. vue --- axios发post请求后台接收不到参数的三种解决方案

    最近用vue  做项目使用axios 发送post 请求时遇到了前端传数据后端接收不到的情况: 后来仔细对比发现axios传值是这样的: 而 ajax 传值是这样的: 一个 Request Paylo ...

  6. 如何解决异步接口请求快慢不均导致的数据错误问题? - DevUI

    DevUI 是一款面向企业中后台产品的开源前端解决方案,它倡导沉浸.灵活.至简的设计价值观,提倡设计者为真实的需求服务,为多数人的设计,拒绝哗众取宠.取悦眼球的设计.如果你正在开发 ToB 的工具类产 ...

  7. Vue+axios统一接口管理

    通过axios请求接口已经很简单了,但最近在做一个vue项目,想着把axios请求再封装一下,这样api就可以只在一处配置成方法,在使用的时候直接调用这个方法. 但咱们不用每个接口都定义成一个啰嗦的a ...

  8. vue axios 发送post请求,后端接收参数为null

    1首先检查自己的传参方式是否正确,我是传一个对象,没有问题,接口也触发了 2查了下资料说是 Content-Type的问题,设置为   'application/x-www-form-urlencod ...

  9. vue axios跨域请求,apache服务器设置

    问题所在axios请求会发送两次请求 也就是说,它会先使用options去测试,你这个接口是否能够正常通讯,如果不能就不会发送真正的请求过来,如果测试通讯正常,则开始正常请求. 思路: 跨域--> ...

  10. Vue axios封装 实现请求响应拦截

    封装 axios.js import axios from 'axios' import { baseURL } from '@/config' class HttpRequest { constru ...

随机推荐

  1. 自有Jar包生成Docker镜像

    前言 经常会有些自己写的一些SpringBoot小项目,为了实现一些小的功能/需求,但是部署的时候,不管是生成jar包,还是war包部署到tomcat中,都容易因为需要部署的环境(比如java版本.t ...

  2. Typroa主题替换

    Typroa主题替换 从这里下载主题 1.解压后: 2.拷贝到typroa的主题目录下(打开typroa -> 偏好设置 -> 外观 -> 打开主题文件夹) 3.拷贝后: 4.重新打 ...

  3. PM-如何优雅的抄袭代码?世上所有代码都是一大抄

    你借了我的思想,在我的思想上,发展出一套理好的思想. 你借了我的代码,在我的代码上,开发出一套理好的代码.   你们知道程序员最熟悉,最熟练,最常用的两个快捷键是哪两个吗?没错,估计你现在心中所想的就 ...

  4. Flutter之GetX之路由管理

    GetX之路由管理 GetX有一套完整的路由管理,并且不需要context上下文,API非常简洁 直接导航 导航到新的页面 Get.to(NextScreen()); 返回,此方法可以用于关闭Snac ...

  5. Flutter GestureDector点击空白区域不响应

    GestureDector点击空白区域不响应 当GestureDector嵌套Container时,当Container子组件为Text时,点击空白区域不响应点击事件 GestureDetector( ...

  6. MyBatisPlus中updateById与updateAllColumnById方法区别

    实现 updateById方法在插入时,会根据实体类的每个属性进行非空判断,只有非空的属性所对应的字段才会出现在SQL语句中. updateAllColumnById方法在插入时,不管属性是否为空,属 ...

  7. Qt/C++音视频开发70-无感切换通道/无缝切换播放视频/多通道流畅切换/不同视频打开无缝切换

    一.前言 之前就写过这个方案,当时做的是ffmpeg内核版本,由于ffmpeg内核解析都是代码实现,所以无缝切换非常完美,看不到丝毫的中间切换过程,看起来就像是在一个通道画面中.其实这种切换只能说是取 ...

  8. Qt音视频开发11-通用监控布局控件(开源)

    一.前言 自从做监控系统以来,就一直有打算将这个功能独立出来一个类,这样的话很多系统用到此类布局切换,通用这个类就行,而且后期此布局会增加其他异形布局,甚至按照16:9之类的比例生成布局,之前此功能直 ...

  9. Qt音视频开发01-共享解码线程(耗时一年/性能凶残/至臻完美)

    一.前言 大概在8年前就开始用ffmpeg做视频解码的显示,第一个版本就100行代码左右,功能极其简单,就是开个线程解码视频流转成图片发给主界面绘制.时间过得真快,从当初的一胎到现在二胎都上学了三胎计 ...

  10. Qt编写安防视频监控系统27-GPU显示

    一.前言 之前用ffmpeg解码的时候,已经做了硬解码的处理,比如支持qsv.dxva2.d3d11va等方式进行硬解码处理,但是当时解码出来以后,还是重新转成了QImage来绘制,这样就大打折扣了, ...