Element-Ui 之 Upload 组件, 利用 axios+ 腾讯云 cos 上传

本贴最后更新于 1810 天前,其中的信息可能已经事过境迁

利用腾讯云 cos 做文件服务器,配合 element-ui 的 upload 组件实现。

腾讯 cos 上传主要分为三个步骤

  1. 设置文件存储位置并返回上传文件地址
  2. 将文件转化为二进制流
  3. 通过二进制流进行文件上传

设置文件存储位置

通过生成 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);
  • Element-UI
    2 引用 • 17 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    265 引用 • 666 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...