您现在的位置是:网站首页> 编程资料编程资料

实现一个Vue版Upload组件_vue.js_

2023-05-24 305人已围观

简介 实现一个Vue版Upload组件_vue.js_

前言

之前对一些主流手机拍出的照片大小做过对比,华为P30拍出的照片3M左右,同事的小米9不知开启了什么模式拍出了10M以上的照片。照片太大了对服务端上传文件造成了不小的压力,对此,后端对前端提出了图片上传前对图片进行压缩。我们目前所用的UI库Upload组件并不支持对上传的图片进行压缩,所以花了一点时间自己写了上传的组件。

今天分享我的第N个Vue组件,Upload

1.组件设计

  • 只有图片裁进行压缩,文件没法压缩。
  • 超过规定大小的图片裁进行压缩,不应该是个图片就压缩,内存过下的图片没必要压缩。
  • 自行定义图片压缩的的宽度,高度按比例自动适配。
  • Upload组件的禁用,该有的基本功能。
  • 文件上传进度。
  • 可接管文件上传。
  • 等等围绕以上几个点开始扩展。

组件实现

1.mixins

export default { props: { icon: { //上传组件的占位图 type: String, default: "iconcamera" }, size: { //图片超过指定大小不让上传 type: Number, default: 3072 }, disabled: { //禁止上传 type: Boolean }, iconSize: { //占位icon的大小 type: Number, default: 24 }, name: { //input的原生属性 type: String, default: 'file' }, accept: { //接受上传的文件类型 type: Array, default() { return []; } }, acceptErrorMessage: { //文件类型错误的提示内容 type: String, default: '文件类型错误' }, compress: { //是否开启图片压缩 type: Boolean, default: true, }, compressSize: { //超过大小的图片压缩 type: Number, default: 512, }, data: { //上传附带的内容 type: Object, default() { return {}; }, }, action: { //上传地址 type: String, default: '', }, headers: { //设置上传的请求头部 type: Object, default() { return {}; }, }, imgWidth: { //图片压缩时指定压缩的图片宽度 type: [Number, Boolean], default: 800, }, quality: { //图片压缩的质量 type: Number, default: 1, }, beforeUpload: { //上传文件之前的钩子 type: Function }, onSuccess: { //上传成功的钩子 type: Function }, onError: { //上传失败的钩子 type: Function }, onLoadend: { //文件上传成功或者失败都会执行的钩子 type: Function }, onProgress: { //文件上传进度的钩子 type: Function }, onSuccessText: { //上传成功的提示内容 type: String, default: '上传成功' }, onErrorText: { //上传失败的提示内容 type: String, default: '上传失败' }, beforeRemove: { //删除文件的钩子 type: Function }, showRemove: { //是否展示删除icon type: Boolean, default: true }, type: { //单文件上传还是多文件上传 type: String, default: 'single', validator: function (value) { return ["single", "multiple"].includes(value); } }, maxNumber: { //多文件上传最多上传的个数 type: Number }, isImage: { //文件是否为图片 type: Boolean, default: true } } }

2. 上传组件的实现

template

文件压缩实现:

canvasDataURL(base) { const img = new Image(); img.src = base; const that = this; function ImgOnload() { /** * 计算生成图片的宽高 */ const scale = this.width / this.height; const width = that.imgWidth === false || this.width <= that.imgWidth ? this.width : that.imgWidth; const height = width / scale; const canvas = that.$refs.canvas; canvas.width = width; canvas.height = height; //利用canvas绘制压缩的图片并生成新的图片 const context = canvas.getContext("2d"); context.drawImage(this, 0, 0, width, height); canvas.toBlob( blob => { that.file = blob; that.upload(blob); that.$emit("on-change", blob, that.options); }, "image/png", that.quality ); /** * 使用完的createObjectURL需要释放内存 */ window.URL.revokeObjectURL(this.src); } img.onload = ImgOnload; }

上传文件的实现:

export function fetch(options, file) { if (typeof XMLHttpRequest === 'undefined') { return; } const xhr = new XMLHttpRequest(); const action = options.action; if (xhr.upload) { xhr.upload.onprogress = function progress(e) { if (e.total > 0) { e.percent = e.loaded / e.total * 100; } options.uploadProgress(e); }; } const formData = new FormData(); formData.append(options.name, file, options.fileName); for (const key in options.data) { formData.append(key, options.data[key]); } // 成功回调 xhr.onload = (e) => { const response = e.target.response; if (xhr.status < 200 || xhr.status >= 300) { options.uploadError(response); return; } options.onload(response); }; // 出错回调 xhr.onerror = (e) => { const response = e.target.response; options.uploadError(response); }; // 请求结束 xhr.onloadend = (e) => { const response = e.target.response; options.uploadLoadend(response); }; xhr.open('post', action, true); const headers = options.headers; for (const key in headers) { if (headers[key] !== null) { xhr.setRequestHeader(key, headers[key]); } } xhr.send(formData); }

3. 完整的代码

上传组件:

utils.js:获取文件的后缀

/** * 获取文件的后缀 * @param {*} file */ export const getType = file => file.s
                
                

-六神源码网