0%

之前上传图片、文件一般都在七牛云,近期由于公司的服务器等资源全部都在阿里云,上传图片也改为了阿里云直传。我们目前采用的是服务器端签名后直传的方式,据说说下前端的实现:
刚开始我们采用的是没有处理图片信息,先请求接口从服务器端获取到阿里云的签名信息,然后直接上传的从本地获取到的file文件:

uploadImg() {
      let data = this.data;//服务器返回给你的签名信息,因为我们是用vue是实现的,获取签名成功后数据保存在data里
      const key = data.dir + new Date().getTime() + '_' + this.file.name;
      var request = new FormData(),
      request.append("OSSAccessKeyId", data.accessid); //Bucket 拥有者的Access Key Id。
      request.append("policy", data.policy); //policy规定了请求的表单域的合法性
      request.append("Signature", data.signature); //根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性
      request.append("key", key); //文件名字,可设置路径
      request.append("success_action_status", "200"); // 让服务端返回200,不然,默认会返回204
      request.append('file', this.file);//需要上传的文件 file

      axios({
        url: data.host,//需要上传的阿里云url
        data: request,
        method: "post",
        headers: { "Content-Type": "multipart/form-data" }//因为是formData形式上传的,所以需要加上这句
      })
        .then(res => {
          return res.data;
        })
        .then(rst => {
          this.imgUrl = data.host + "/" + key;
        });
    },
后来发现这种上传手机原图,图比较大的情况,上传会特别慢,从阿里云下载的时候图片加载也很影响用户体验,于是就加入了裁切和压缩图片的功能,我们运用的是vue的插件:vue-core-image-upload 首先安装:
npm install vue-core-image-upload --save
然后编辑代码:
    <\vue-core-image-upload 无需前边的’\‘ :class="['btn', 'btn-primary']" :crop="local" 图片本地裁切,服务器端裁切为“server” cropratio="1:1" 图片裁切比例 inputaccept="image/*" 接收的文件类型 :max-file-size="5242880" 图片的大小 :compress="60" 压缩比例,数字越小,压缩的越模糊 :isxhr="isXhr" 不使用插件自带的上传,自定义上传图片 @imagechanged="imagechanged" 当input框改变选择图片时候触发,会返回input的获取的图片数据 @imageuploading="imageuploading" 当图片上传过程中触发,你可以自定义你需要处理的内容比如显示加载动画等。>\<\ vue-core-image-upload>//无需“\”

js部分:


import VueCoreImageUpload from ‘core/vue-core-image-upload.vue’

export default {
components: {
‘vue-core-image-upload’: VueCoreImageUpload,
},
data() {
return {

}

},
methods: {
imageuploading() {

}
imagechanged(){

}

}
};

好了,到此本以为事情圆满解决了,却又发现了另外的问题,上传到阿里云是用formData的方式上传的,图片裁切过后得到的是Base64格式的图片,这时就需要把Base64格式的图片转成Blob格式,再使用formData方式上传

Base64格式转换为Blob:


function getBlobBydataURI(dataURI,type) {
var binary = atob(dataURI.split(‘,’)[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}

    return new Blob([new Uint8Array(array)], {type:type });  
} 


最后的上传代码js部分:(html部分如上)


import utils from “@/js/utils”;
import axios from “axios”;
import VueCoreImageUpload from “vue-core-image-upload”;
export default {
name: “”,
components: {
“vue-core-image-upload”: VueCoreImageUpload
},
data() {
return {
imgUrl:””
local: “local”,
isXhr: false,
file: “”,
data: “”,
isShowLoading: false
};
},
methods: {
imagechanged(data) {
this.file = data;
this.getOssToken();
},
imageuploading(data) {
this.isShowLoading = true;
},
uploadImg() {
let data = this.data;
const key = data.dir + new Date().getTime() + “.png”;//因为Base64格式的图片没有后缀,我们给默认png格式的图片
var $Blob = utils.getBlobBydataURI(this.file, “image/png”);
var request = new FormData()
request.append(“OSSAccessKeyId”, data.accessid); //Bucket 拥有者的Access Key Id。
request.append(“policy”, data.policy); //policy规定了请求的表单域的合法性
request.append(“Signature”, data.signature); //根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性
request.append(“key”, key); //文件名字,可设置路径
request.append(“success_action_status”, “200”); // 让服务端返回200,不然,默认会返回204
request.append(“file”, $Blob);

  axios({
    url: data.host,
    data: request,
    method: "post",
    headers: { "Content-Type": "multipart/form-data" }
  })
    .then(res => {
      return res.data;
    })
    .then(rst => {
      this.imgUrl = data.host + "/" + key;
      this.isShowLoading = false;
    });
},

getOssToken() {//获取阿里云签名
  this.$api.getOssToken().then(res => {
    this.data = res;
    this.uploadImg();
  });
}

},

};

突然想起来阿里云上传还有个很大的坑,其实文档上有写,但是很多人忽略的问题:就是跨域,记得在你的阿里云上设置一下这个就好了
alt

上传文件参考博客:https://gilea.cn/article/11399260-9be2-11e8-b2a2-b1037d08a2a6

vue上传裁切压缩图片插件文档:https://vanthink-ued.github.io/vue-core-image-upload/index.html#/cn/home

图片、音频等文件上传自己的服务器会占用很多的资源,增加服务器的压力,这是后可以考虑上传到第三方,比如七牛云。上传七牛云首先要注册自己的七牛云账号,在此就不赘述。

获取七牛云token(需要后台去获取,暴露接口给前端)

调用小程序API获取图片,上传至七牛云


takePhoto() {
var that = this
wx.chooseImage({
count: 1,
sourceType: [‘camera’],
success: function(res) {
var filePath = res.tempFilePaths[0];
// 交给七牛上传
var date = new Date().getTime();
qiniuUploader.upload(filePath, (res) => {
// 每个文件上传成功后,处理相关的事情
// 其中 info 是文件上传成功后,服务端返回的json,形式如
// {
// “hash”: “Fh8xVqod2MQ1mocfI4S4KpRL6D98”,
// “key”: “gogopher.jpg”
// }
// 参考http://developer.qiniu.com/docs/v6/api/overview/up/response/simple-response.html
that.setData({
‘imageURL’: res.imageURL,
});
}, (error) => {
console.log(‘error: ‘ + error);
}, {
region: ‘ECN’,
domain: ‘https://yourUrl.com', // // bucket 域名,下载资源时用到。如果设置,会在 success callback 的 res 参数加上可以直接使用的 ImageURL 字段。否则需要自己拼接
key: date + ‘.jpg’, // [非必须]自定义文件 key。如果不设置,默认为使用微信小程序 API 的临时文件名
// 以下方法三选一即可,优先级为:uptoken > uptokenURL > uptokenFunc
uptoken: that.data.uptoken, // 由其他程序生成七牛 uptoken//调用接口从后台获取的token
uptokenURL: that.data.uptoken, // 从指定 url 通过 HTTP GET 获取 uptoken,返回的格式必须是 json 且包含 uptoken 字段,例如: {“uptoken”: “[yourTokenString]”}
uptokenFunc: function() {
return that.data.uptoken;
}
}, (res) => {
// console.log(‘上传进度’, res.progress)
// console.log(‘已经上传的数据长度’, res.totalBytesSent)
// console.log(‘预期需要上传的数据总长度’, res.totalBytesExpectedToSend)
if (res.progress == 100) { //上传完成

      }
    });
  },
  fail: (res) => {
    console.log(res)
  }
})

}

音频的上传类似,需要配置一些音频相关的options


startAudio(){
var that=this

const options = {
  duration: 30000, //指定录音的时长,单位 ms
  sampleRate: 16000, //采样率
  numberOfChannels: 1, //录音通道数
  encodeBitRate: 96000, //编码码率
  format: 'mp3', //音频格式,有效值 aac/mp3
  frameSize: 50, //指定帧大小,单位 KB
}
//开始录音
recorderManager.start(options);
recorderManager.onStart(() => {
  console.log('开始录音')
});

recorderManager.onStop((res) => {//停止录音

  this.tempFilePath = res.tempFilePath;
  console.log('停止录音', res.tempFilePath)
  const {
    tempFilePath
  } = res

  //上传七牛云
  var filePath = res.tempFilePath;
  // 交给七牛上传
  var date = new Date().getTime();
  qiniuUploader.upload(filePath, (res) => {
    that.setData({
      'audioUrl': res.imageURL,
    });
  }, (error) => {
    console.log(res)
  }, {
    region: 'ECN',
    domain: 'https://yourUrl.com',
    key: date + '.mp3',
    uptoken: that.data.uptoken,
    uptokenURL: that.data.uptoken,
    uptokenFunc: function() {
      return that.data.uptoken;
    }
  }, (res) => {
    if (res.progress == 100) { //上传完成

    }
  });
})

}

先分享到这里,如有其它问题可以参看七牛云的相关文档:
https://github.com/gpake/qiniu-wxapp-sdk