vue移动端van-uploader将base64转为二进制文件流上传服务器

2,354 阅读2分钟

背景

vue2.x项目,vantUI框架,实现上传图片和视频到后端服务器。

实现

  • 支持移动端调起手机摄像头现拍以及选择系统中的文件上传

    van-uploader组件API:

    image.png

    注意:当没有设置capture时,会调用系统默认行为,让你选择相机还是文件。当你设置该属性时候,就不会有选择界面!!!如果不喜欢这个系统自带界面可以自己封装一个选择界面,但是,我试了,发现不简单,主要是van-uploader提供的回调函数不够全面,需要自己封装。

  • 将base64转为二进制文件流

    van-uploade默认是返回的base64格式文件,不管是图片还是视频。后端需要二进制文件,所以需要进行转换。参考链接:blog.csdn.net/weixin_4413…

    // bae64转文件对象
    function dataURLtoFileFun (dataurl, filename) {
      // 将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
      const arr = dataurl.split(',')
      const mime = arr[0].match(/:(.*?);/)[1]
      const bstr = atob(arr[1])
      let n = bstr.length
      const u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    }

  • 上传服务器

    使用axios进行上传,但是上传文件的话需要进行配置,如下

    const token = getToken()
    const instance = axios.create({
      baseURL: process.env.VUE_APP_URL,
      headers: {
        //自定义token字段
        Authorization: token,
        //重要字段,使用formData提交
        'Content-Type': 'multipart/form-data'
      },
      //这个是看了一个链接说,axios拦截器会把文件形式转成对象格式,就会上传失败,链接在下面:
      
      transformRequest: [
        function (data) {
          return data
        }
      ]
    })
    

    transformRequest参考链接: www.cnblogs.com/czy960731/p…

    注意:因为我项目中接口都是会经过axios拦截器的,据说会把文件流转成对象,于是我就创建了一个新的axios副本。

    调用接口:

    // 参数为单个文件
    function upLoaderImg (file, fileTimestamp) {
      //  file为 你读取成功的回调文件信息,fileTimestamp为时间戳(后端要求的)
      //  new 一个FormData格式的参数
      const fromData = new FormData()
      fromData.append('file', dataURLtoFileFun(file.content, file.file.name))
      fromData.append('fileTimestamp', fileTimestamp)
      return new Promise((resolve, reject) => {
        //  把 uploadUrl 换成自己的 上传路径
        instance
          .post('uploadUrl', fromData)
          .then(res => {
            console.log('看下是否上传成功', res)
            if (res && res.data && res.data.status === 1) {
              //  如果为真 resolve出去
              resolve(res.data)
            } else {
              //  否则 Toast 提示
              Toast.fail(res.data && res.data.msg)
              reject(res.data)
            }
          })
          .catch(err => {
            Toast.fail('系统异常')
            reject(err)
          })
      })
    }
    
  • 上传多个文件

    原本以为是以数组的形式去上传多个文件,单个文件作为数组的一个文件对象元素,结果行不通,也不知道是哪儿错了,大概率是这种形式不能通过formData提交。

    然后去看了element-ui封装好的文件上传形式,是支持多个文件上传的,但是他的形式是,每个文件发送一个上传请求,于是我也这样做好了哈哈哈哈哈哈