任务描述: 一个涉及APP发布和升级的后台管理系统,需要前端上传apk、.APK、.ipa、.IPA的Android包或者IOS包,转换成二进制的形式上传至腾讯云,腾讯云返回200标识成功,成功后调用保存接口, 返回403表示失败。
思路:后台要求非formdata上传,所有不能设置
headers: { 'Content-Type': ' multipart/form-data' },
只能用Blob或者FileReader。又要求bindary形式,只能用fileReader。
采坑点一:腾讯云采用PUT上传, 二进制的headers头部,要设置成
headers: {
'Content-Type': 'application/octet-stream'
}
采坑点二:用fileReader读取的文件,文件流保存在event.target.result里面,即要传给后台的数据
采坑点三:fileReader的事件和方法具体情况具体分析。一开始我用的是readAsDataURL(), 此时返回的是base64的URL,而非binary对象,后来改为readAsArrayBuffer()
https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
采坑点四:我们框架用的element,上传用的upload组件。upload返回的file对象跟原生的有点区别,具体对象内容放在了file.raw里面,即file.raw = 原生file[0],一开始直接传的element的file对象给FileReader, 方法会报错。
具体实现:
const reader = new FileReader()
reader.readAsArrayBuffer(this.uploadData.file.raw)
reader.onload = async(event) => {
axios.put(data.uploadUrl, event.target.result, {// event.target.result为读取到的流
headers: {
'Content-Type': 'application/octet-stream'
}
}).then(res => {
// 成功之后的方法
}).finally(_ => {
// 最终执行的方法 前面读取之前加了loading 所以这里做清除操作
loading.close()
})
}
reader.onerror = (event) => {
// 读取失败 提示
return this.$message.error(this.$kiwi.get('appModel.tips4'))
}
此时FileReader读取文件上传腾讯云的操作就OK了,后台会解析拿到的包,返回相应的数据。
其次附上常用到的下载操作方法,相对上传比较简单,注意一点就是封装方法的responseType要设置为‘blob’,表明返回服务器返回的数据类型
responseType: 'blob'
/** * 文件流下载 *
@param {Object} res 接口返回信息 *
@param {String} type 文件类型 *
@param {String} filename 下载后文件名
*/
export function downloadFile(res, type, filename) { // 这里res是返回的blob对象
const blob = new Blob([res], { type: type })
let v_filename = ''
if (!filename) {
const contentDisposition = res.headers['content-disposition'] // 从response的headers中获取filename, 后端response.setHeader("Content-Disposition", "attachment; filename=xxxx.xls") 设置的文件名;
if (contentDisposition) {
const patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
const result = patt.exec(contentDisposition)
v_filename = result[1] // 下载后文件名
} else { // content-disposition如果没有获取到,暂定文件名为SF
v_filename = 'XX' // 下载后文件名
}
} else {
v_filename = filename
}
// 判断是不是ie浏览器
if (!!window.ActiveXObject || 'ActiveXObject' in window) {
window.navigator.msSaveOrOpenBlob(blob, v_filename)
} else {
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.style.display = 'none'
downloadElement.href = href
downloadElement.download = v_filename // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
}}