评论

http上传云文件图片跨域的另一种解决方案

http上传云文件图片跨域的另一种解决方案

vue做个后台管理,用微信提供的http操作云储存上传文件会出现跨域问题,我只想搭个前端就能直接上传到云文件,不想再搭个后台中转。

换个思路,云函数是可以直接请求的,云函数里是可以直接上传图片到云文件的

由上可得 可以把图片数据传到云函数在云函数中上传图片
然而 测试发现云函数调用时有最大数据限制,大概十几kb就报错了,这肯定时不行的

但是
数据库新增是可以直接操作的,

来一波骚操作,先把图片数据转换成base64的字符串上传到云数据库,把_id传给云函数,让云函数从数据库中取出图片的数据,转换成

new Buffer(base64Data, 'base64')

哈哈哈哈哈哈哈哈哈哈哈,完美上传图片

然而事情并没有那么简单~~
上传到云数据库时也有数据大小限制的
经过测试 base64字符串在500000字符长度是可以的(大概400kb)
在600000字符长度就会报错,

所以我们还要对上传的图片数据做分批上传

以上测试都没有错误截图了,只有已经可以完美上传的代码(请勿完全复制,根据你项目实际情况修改)


export function add(token, datastr) {
  const params = {
    "env": envid,
    "query": "db.collection(\"testadd\").add({data:"+ datastr + "})",
  }
  // console.log("==params==" + JSON.stringify(params))
  var url = 'api/tcb/databaseadd?access_token=' + token;
  return request({
    url: url,
    method: 'POST',
    data: params
  })
}


 addObj({ commit },param) {
    return new Promise((resolve, reject) => {
      var accessToken=state.token
      if(accessToken==null){
        accessToken=getToken()
      }
      add(accessToken,JSON.stringify(param)).then(response => {
        // 
        // console.log('上传数据返回结果',response)
        resolve(response)
        if(response.errcode == 0){
          // if(response.data[0] != null){
          //   resolve(JSON.parse(response.data[0]))
          // }else{
          //   resolve(null)
          // }
        }        
      }).catch(error => {
        reject(error)
      })
    })
  },
  
  //这是html中的
  <input type="file" @change="handleChange" ref="fileInput1"  accept="image/*">

  //input上传文件的回调
  handleChange(info) {
          const file = this.$refs.fileInput1.files[0]
          const fr = new FileReader()
           var self = this
          fr.onload = (e) => {
            try {
              console.log('file', fr)
              // self.imgData = fr.result
               self.imgData = {type:"Buffer", data: fr.result}
            } catch (error) {
               self.$message.error(`${file.name} 打开失败`);
            }
          }

          fr.readAsDataURL(file)
          info.target.value= ""
      },

  	//点击确定上传按钮回调
     onModalOk(){
       var imgData = self.imgData.data 
            var splitCount = 500000
            //长度大于一定时就要分断上传
            // if(imgData.length > splitCount){
            //   imgData = imgData.substring(0, splitCount)
            // }

            var count = Math.ceil(imgData.length / splitCount) //要上传的次数
            var hasAdd = 0
            var idList = []
            for (let index = 0; index < count; index++) {
              const subData = imgData.substring(splitCount * index, splitCount * (index + 1));
               self.$store
                .dispatch("user/addObj", {name: 'testName.png', fileStream: subData, index: index})
                .then(response => {
                    hasAdd += 1
                    idList.push(response.id_list[0])
                    console.log('当前hasAdd', idList, hasAdd, count)
                    if(hasAdd == count){
                      self.$store
                        .dispatch("user/updateImgObj", {id: idList})
                        .then(response2 => {
                          self.listLoading = false
                          console.log('关闭返回的结果2', response2)
                        }).catch(error => {
                          self.listLoading = false
                          self.$message.error('上传失败');
                        })
                    }
                }).catch(error => {
                  self.listLoading = false
                  self.$message.error('上传失败');
                })
            }
         }

然后是云函数中的代码:

		// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()
const db = cloud.database()
const _ = db.command

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  var arr = []
  for (var i = 0; i < event.id.length; i++){
      var data = await db.collection("testadd").doc(event.id[i]).get()
    arr.push(data.data)
  }
  arr.sort(function(a, b){
    return a.index - b.index
  })
  
  var base64Data = ''
  for (var i = 0; i < arr.length; i++){
    base64Data += arr[i].fileStream
  }
  // return data
  base64Data = base64Data.replace(/^data:image\/\w+;base64,/, "");

  var result = await cloud.uploadFile({
    cloudPath: arr[0].name,
    fileContent: new Buffer(base64Data, 'base64')  //{ type: 'Buffer', data: data.fileStream},
  })
  // var result = {}
  // result.data = base64Data'
  //上传完成后删除数据库中的数据
  for (var i = 0; i < event.id.length; i++) {
    await db.collection("testadd").doc(event.id[i]).remove()
  }
 
  return result
}

研究了一天,上传图片这块微信的文档里只是简单说了上传格式,却没有例子,一次次尝试才测试出什么样的格式存到云函数中是有效的图片,分享给广大有需求的程序员,减少需要研究花费的时间

最后一次编辑于  2019-12-06  
点赞 4
收藏
评论

3 个评论

  • LYB
    LYB
    2020-01-08

    你在调用云函数的时候不也要发请求?这不还是一样会跨域

    2020-01-08
    赞同 1
    回复
  • 舔酥
    舔酥
    2020-03-23

    问下楼主,怎样直接在前端上传markdown文件?

    2020-03-23
    赞同
    回复
  • 王浩Hanks🇨🇳
    王浩Hanks🇨🇳
    2019-12-06

    不错,点赞

    2019-12-06
    赞同
    回复
登录 后发表内容