利用腾讯云 cos 做文件服务器,配合 element-ui 的 upload 组件实现。
腾讯 cos 上传主要分为三个步骤
- 设置文件存储位置并返回上传文件地址
- 将文件转化为二进制流
- 通过二进制流进行文件上传
设置文件存储位置
通过生成 guid 保证上传的文件不会被覆盖
function guid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4();
}
设置并获取 cos 文件存储路径
_axios
.get(url + "?path=" + guid())
.then(data => {
const uploadUrl = data;
// TODO 上传文件
});
将文件转化为二进制流
主要利用 FileReader 实现。
let fr = new FileReader();
fr.readAsDataURL(file);
fr.addEventListener(
"load",
() => {
let arr = fr.result.split(",");
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
// TODO 设置文件存储路径
},
false
);
上传文件至 cos 服务器
_axios
.put(uploadUrl, binary, {
timeout: 60 * 60 * 1000,
onUploadProgress: e => {
if (e.total > 0) {
e.percent = (e.loaded / e.total) * 100;
}
const { onProgress } = option;
if (
Object.prototype.toString.call(onProgress) === "[object Function]"
) {
onProgress(e);
}
},
headers: {
"Content-Type": fileType
}
})
.then(() => {
// 上传成功
})
.catch(error => {
// 上传失败
});
完整代码如下
import _axios from "@/plugins/axios";
/**
* 生成GUID
*/
function guid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4();
}
/**
* 腾讯云cos文件上传
* @param {String} uploadUrl cos上传路径
* @param {Blob} binary 二进制文件
* @param {String} fileType 文件类型,默认为image/jpeg
* @param {Object} option ElementUI上传组件配置
*/
function upload(uploadUrl, binary, fileType = "image/jpeg", option = {}) {
return new Promise((resolve, reject) => {
_axios
.put(uploadUrl, binary, {
timeout: 60 * 60 * 1000,
onUploadProgress: e => {
if (e.total > 0) {
e.percent = (e.loaded / e.total) * 100;
}
const { onProgress } = option;
if (
Object.prototype.toString.call(onProgress) === "[object Function]"
) {
onProgress(e);
}
},
headers: {
"Content-Type": fileType
}
})
.then(() => {
resolve(uploadUrl);
})
.catch(error => {
reject(error);
});
});
}
/**
* 腾讯云cos上传,获取文件上传路径,并上传文件
* @param {String} url 文件上传路径
* @param {File} file 上传文件
* @param {Object} option 上传配置
*/
export function fileUpload(url, file, option = {}) {
return new Promise((resolve, reject) => {
let fr = new FileReader();
fr.readAsDataURL(file);
fr.addEventListener(
"load",
() => {
let arr = fr.result.split(",");
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
_axios
.get(url + "?path=" + guid())
.then(data => {
const uploadUrl = data;
return upload(uploadUrl, u8arr, file.type, option);
})
.then(path => {
const url = path.split("?")[0];
resolve(url);
})
.catch(reason => {
reject(reason);
});
},
false
);
});
}
/**
* 重写ElementUI上传时ajax方法
* @param {Object} option ElementUI上传组件配置
*/
export function uploadOverrideElement(option) {
fileUpload(option.action, option.file, option)
.then(url => {
option.onSuccess(url);
})
.catch(reason => {
option.onError(reason);
});
}
最后
在引用 Upload 时重写 httpRequest,即可
import { Upload } from "element-ui";
import { uploadOverrideElement } from "@/utils/uploadUtils";
Upload.props.httpRequest = {
type: Function,
default: uploadOverrideElement
};
Vue.use(Upload);
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于