最近做了一个项目,需求是上传文档,文档类型多种,图片,视频,文件,doc,xls,zip,txt 等等,而且文档类型可能是大文件,可能得上百兆,甚至超过1G。
腾讯云文档地址:https://cloud.tencent.com/document/product/436/31953 腾讯云可以支持5G 的文件,还是很厉害的。
 这里只要是讲一下使用这个SDK的流程,因为第一次看文档的时候,文档介绍很简洁,甚至有点笼统。我当时都是很懵的,无从下手。
 这个是小程序小程序直传实践的实现步骤,同样使用于对象存储。,我们一开始研究SDK对象储存觉得很难,然后想简单点,搞个对象储存,不这么麻烦。最后是借鉴了这里的步骤思路。
 1、登录后台创建桶,地域
 2、获取秘钥
 3、小程序配置白名单
 
 核心代码就这么点,选择文件,将后缀传给服务器,服务器根据后缀,生成一个cos文件路径,计算对应的签名,返回URL和签名信息给前端。
 
 
最终效果
 
wxcs
 page{
 font-size: 28rpx;
 color: #333;
 }
 .content-row {
 display: flex;
 height: 48px;
 color: #333;
 padding-left: 20rpx;
 line-height: 48px;
 border-bottom: 1rpx solid #ddd;
 }
.content-rows {
 display: flex;
 color: #333;
 padding-left: 20rpx;
 line-height: 48px;
 }
.content-title {
 width: 190rpx;
 color: #666;
 }
 .click-btn{
 background-color: #E1B368;
 }
 .click-btn-hover{
 background-color: #b98633;
 }
/index.wxss/
 .title {
 display:block;
 box-sizing: border-box;
 padding: 0 5px;
 width: 100%;
 height: 30px;
 line-height: 30px;
 border-top: 1px solid #ccc;
 margin:auto;
 font-size:14px;
 color:#333;
 text-align: left;
 font-weight: bold;
 }
.list-panel{
 width: 100%;
 }
.sub-title{
 display:block;
 box-sizing: border-box;
 padding: 0 5px;
 width: 100%;
 height: 30px;
 line-height: 30px;
 font-size:12px;
 color:#333;
 text-align: left;
 font-weight: bold;
 }
.list {
 margin-top: 10px;
 padding-bottom: 10px;
 width: 100%;
 }
.button {
 font-weight: 500;
 float: left;
 width: 710rpx;
 margin: 0 3px 3px 0;
 text-align: center;
 font-size: 14px;
 height: 60rpx;
 padding-top: 6px;
 }
 .click-btn2 {
 background-color: #eee;
 }
.click-btn-hover2 {
 background-color: #d3d3d3;
 }
wxjs
 
 Js部分引入了两个文件,cos-wx-sdk-v5.js 文件可以在github上下载https://github.com/tencentyun/cos-wx-sdk-v5/tree/master/demo
 github上右demo吗,我通过demo自己稍微改造了一下。
 和config,其中config就是配置的一些内容
 
var COS = require(‘…/…/lib/cos-wx-sdk-v5’);
 const app = getApp()
 var config = require(‘…/…/config’)
//这里是获取签名授权
 var getAuthorization = function (options, callback) {
 wx.request({
 method: ‘POST’,
 url: config.stsUrl, // 服务端签名,参考 server 目录下的两个签名例子
 dataType: ‘json’,
 data: {
 uid: wx.getStorageSync(‘uid’),
 token: wx.getStorageSync(‘token’)
 },
 header: {
 ‘content-type’: ‘application/x-www-form-urlencoded’
 },
 success: function (result) {
 var data = result.data.data;
 var credentials = data && data.credentials;
 // if (!data || !credentials) return console.error(‘credentials invalid’);
 console.log(credentials)
 callback({
 TmpSecretId: credentials.tmpSecretId,
 TmpSecretKey: credentials.tmpSecretKey,
 SecurityToken: credentials.sessionToken,
 StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
 ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000900
 });
 },
 });
 };
 var cos = new COS({
 getAuthorization: getAuthorization,
 });
Page({
/**
- 页面的初始数据
 */
 data: {
 itemname: ‘’,
 id: ‘’,
 beizhu: ‘’,
 img: [],
 pdfFile: ‘’,
 fileType: ‘’,
 filekeyname: ‘’,
 jindu: ‘’,
 speed: ‘’,
 datalist:[],
 realimg:[]
 },
 onLoad(options) {
 if (options.id) {
 this.setData({
 id: options.id
 })
 }
},
 handleItem(e) {
 this.setData({
 itemname: e.detail.value
 })
 },
 handlebeizhu(e) {
 this.setData({
 beizhu: e.detail.value
 })
 },
 //核心代码
 postUpload() {
 let that = this
 wx.chooseMessageFile({
 count: 1,
 type: ‘all’,
 success: function (res) {
 let data = res.tempFiles[0]
 console.log(data.name)
 let testarr = []
 testarr.push(data.name.replace(/,/g, ‘’))
 that.setData({
 realimg:that.data.realimg.concat(testarr)
 })
 wx.showLoading({
 title: ‘上传中…’,
 })
 var lastDotIndex = data.name.lastIndexOf(“.”); // 查找最后一个"."的索引
 var secondPart = data.name.slice(lastDotIndex + 1);
 console.log(secondPart)
 cos.uploadFile({
 Bucket: config.Bucket,
 Region: config.Region,
 Key: Date.now() + Math.floor(Math.random() * 1000) + ‘.’+secondPart,
 FilePath: data.path,
 FileSize: data.size,
 SliceSize: 1024 * 1024 * 5, // 文件大于5mb自动使用分块上传
 onTaskReady: function (taskId) {
 TaskId = taskId;
 },
 onProgress: function (info) {
 var percent = parseInt(info.percent * 10000) / 100;
 var speed = parseInt((info.speed / 1024 / 1024) * 100) / 100;
 console.log(that, ‘进度:’ + percent + ‘%; 速度:’ + speed + ‘Mb/s;’);
 that.setData({
 jindu: percent,
 speed: speed
 })
 },
 onFileFinish: function (err, data, options) {
 if(!err){
 console.log(that.data.realimg)
 let arr = []
 arr.push(options.Key)
 that.setData({
 img: that.data.img.concat(arr) //我们自己稍微改造了一下,上传到腾讯云的文件名是在时间戳+3位的随机数,但是显示在本地的文件名是自己原本给文件的命名。(因为大家的文件命名不规范,长长短短,啥都有。统一命名,在腾讯云后台看起来不会奇奇怪怪。)
 })
 }else{
 that.setData({
 realimg:that.data.realimg.pop()
 })
 }
          wx.hideLoading()
          console.log(options.Key + '上传' + (err ? '失败' : '完成'));
        },
      },
      function (err, data) {
        console.log(err || data);
      },
    );
  },
});
},
DelImg(e){
 console.log(e)
 let i = e.currentTarget.dataset.index
 let that = this
 wx.showModal({
 title: ‘提示’,
 content: ‘确定要删除吗?’,
 cancelText: ‘取消’,
 confirmText: ‘确定’,
 success: res => {
 if (res.confirm) {
 that.data.realimg.splice(i, 1);
 that.data.img.splice(i, 1);
 that.setData({
 realimg:that.data.realimg,
 img:that.data.img,
 })
 }
 }
 })
 },
 handlesave() {
 let that = this
 if (!this.data.itemname) {
 wx.showToast({
 title: ‘请填写文件名称’,
 icon: ‘error’,
 duration: 2000
 })
 return
 }
 if (this.data.realimg.length <1) {
 wx.showToast({
 title: ‘请上传文件’,
 icon: ‘error’,
 duration: 2000
 })
 return
 }
 wx.showLoading({
 title: ‘保存中…’,
 })
 // console.log(this.data.fileList1)
 // var img = [];
 // var realimg = [];
// this.data.fileList1.forEach(function (item) {
//   var index = 12
//   // 分割字符串,取前十位  
//   var firstPart = item.slice(0, 13);
//   // 提取下标12之后的内容  
//   var index = 12;
//   var secondPart = item.slice(index + 1);
//   // 提取最后一个"."之后的内容  
//   var lastDotIndex = item.lastIndexOf(".");
//   var thirdPart = item.slice(lastDotIndex + 1);
//   img.push(firstPart + "." + thirdPart);
//   realimg.push(secondPart);
// });
// console.log(img, realimg)
// return
wx.request({
  url: app.globalData.siteurlh5 + '/fileadd.php',
  data: {
    id: this.data.id,
    beizhu: this.data.beizhu,
    uid: wx.getStorageSync('uid'),
    token: wx.getStorageSync('token'),
    title: this.data.itemname,
    img: this.data.img, // 时间戳命名文件
    realimg: this.data.realimg  //文件真实名称
  },
  header: {
    'content-type': 'application/x-www-form-urlencoded'
  },
  method: 'POST',
  success(res) {
    console.log(res, )
    if (res.data.bs == 'success') {
      wx.showToast({
        title: res.data.errmsg,
        duration: 2000,
        icon: 'success'
      })
      setTimeout(() => {
        wx.navigateBack({
          delta: 1,
        })
      }, 2000);
    } else if (res.data.bs == 'failed') {
      wx.showToast({
        title: res.data.errmsg,
        duration: 2000,
        icon: 'error'
      })
    } else if (res.data.bs == 'error') {
      wx.showToast({
        title: res.data.errmsg,
        duration: 2000,
        icon: 'error'
      })
    } else if (res.data.bs == 'guoqi') {
      wx.removeStorageSync('userInfo'); //清除缓存
      wx.removeStorageSync('uid')
      wx.removeStorageSync('token')
      wx.redirectTo({
        url: '../index/index',
      })
    }
  },
  fail(err) {
    console.log(err)
    wx
  },
  complete() {
    // wx.hideLoading()
  }
})
},
 })

 上传完成这个文件后缀名就是我们的文件了。但是它不是完整的路径,完整的路径是在腾讯云上面就可以预览了。如果前端要下载文件,那就再让你的后台把完整的路径传回来。
 
以下是一个简单的上传多种文件类型的方案:
 我们最初是指考虑了简单的上传文件,并没有考虑大的文件,所以超过20M 的文件,这里是不支持的。
 
 wxml
 
 
 
 
 
 项目名称:
 
 
 
 
 
 
 备注:
 
 
 
 
 
 *
 文件:
 
 
 
 
    <view class="bg-img" wx:for="{{imgList1}}" wx:key="index" style="position: relative;">
      <image src="{{item}}" mode="aspectFill" data-url="{{item}}" 
      bindtap='previewImage' data-src="{{item}}" style="width:140rpx;height:140rpx;margin: 10rpx 10rpx 10rpx 0 ;"></image>
      <view bindtap="DelImg" data-index="{{index}}">
        <view style="z-index: 9; margin:10rpx 17rpx 10rpx 0;width: 40rpx;height: 30rpx;background-color: #555;color: white;position: absolute;right: -16rpx;top: -10rpx;text-align: center;line-height: 30rpx;border-radius: 6rpx;">×</view>
      </view>
    </view>
    <view class="bg-img" wx:for="{{videoList1}}" wx:key="index" style="position: relative;">
      <video src="{{item}}" bindtap="previewVideo" 
      data-url="{{item}}" style="width:140rpx;height:140rpx;margin: 10rpx 10rpx 20rpx 0 ;" 
      autoplay="{{isPlay}}" loop="{{false}}" show-center-play-btn='{{true}}' show-play-btn="{{true}}" 
      controls picture-in-picture-mode="{{['push', 'pop']}}">
      </video>
      <view bindtap="DelImg2" data-index="{{index}}">
        <view style="z-index: 9; margin:10rpx 17rpx 10rpx 0;width: 40rpx;height: 30rpx;background-color: #555;color: white;position: absolute;right: -16rpx;top: -10rpx;text-align: center;line-height: 30rpx;border-radius: 6rpx;">×</view>
      </view>
    </view>
    <view class="bg-img" wx:for="{{fileList1}}" wx:key="index" style="position: relative;">
      <input placeholder="查看附件" class="click-btn2" hover-class="click-btn-hover2" disabled bindtap="handledownload" data-img="{{item}}"  
      placeholder-style="color:#888" name="input" style="padding: 0px 10px;width:640rpx;font-size: 28rpx;color: #888;height: 70rpx;line-height: 70rpx;margin-top: 10rpx;"></input>
      <view bindtap="DelImg3" data-index="{{index}}">
        <view style="z-index: 9; margin:10rpx 17rpx 10rpx 0;width: 40rpx;height: 30rpx;background-color: #555;color: white;position: absolute;right: -16rpx;top: -10rpx;text-align: center;line-height: 30rpx;border-radius: 6rpx;">×</view>
      </view>
    </view>
    <view bindtap="uploadFileTap" data-id="1" >
      <view style="width:140rpx;height:140rpx;border:1px dashed #ddd;text-align:center;background:white;position: relative;margin:10rpx 0;">
        <image src="/images/upload.png" style="width:45rpx;height:37rpx;margin-top: 35rpx;"></image>
        <view style="font-size: 20rpx;color: #333;">
          文件
        </view>
      </view>
    </view>
  </view>
</view>
.content-rows {
 display: flex;
 color: #333;
 padding-left: 20rpx;
 line-height: 48px;
 }
.content-title {
 width: 190rpx;
 color: #666;
 }
 .click-btn{
 background-color: #ff5a28;
 }
 .click-btn-hover{
 background-color: #d44215;
 }
/index.wxss/
 .title {
 display:block;
 box-sizing: border-box;
 padding: 0 5px;
 width: 100%;
 height: 30px;
 line-height: 30px;
 border-top: 1px solid #ccc;
 margin:auto;
 font-size:14px;
 color:#333;
 text-align: left;
 font-weight: bold;
 }
.list-panel{
 width: 100%;
 }
.sub-title{
 display:block;
 box-sizing: border-box;
 padding: 0 5px;
 width: 100%;
 height: 30px;
 line-height: 30px;
 font-size:12px;
 color:#333;
 text-align: left;
 font-weight: bold;
 }
.list {
 margin-top: 10px;
 padding-bottom: 10px;
 width: 100%;
 }
.button {
 float: left;
 margin: 0 3px 3px 0;
 text-align: left;
 font-size: 14px;
 height: 28px;
 line-height:28px;
 padding:0 10px;
 }
 .click-btn2 {
 background-color: #eee;
 }
.click-btn-hover2 {
 background-color: #d3d3d3;
 }
wxjs
 const app = getApp()
 Page({
/**
- 页面的初始数据
 */
 data: {
 itemname: ‘’,
 id: ‘’,
 beizhu: ‘’,
 imgList1: [],
 fileList1:[],
 videoList1:[],
 pdfFile: ‘’,
 fileType:‘’
 },
handledownload(e) {
 console.log(e)
 let img = e.currentTarget.dataset.img
 wx.downloadFile({
 url: img,
 success: function (res) {
 // console.log(res)
 // return
 var Path = res.tempFilePath //返回的文件临时地址,用于后面打开本地预览所用
 wx.openDocument({
 filePath: Path,
 fileType: Path.split(“.”)[Path.split(“.”).length - 1],
 showMenu: true,
 success: function (a) {},
 fail: function (a) {
 console.log(a)
 wx.showToast({
 title: ‘文件打开失败’,
 icon: ‘none’,
 duration: 2000,
 })
 }
 })
 }
 })
 },
 DelImg(e){
 console.log(e)
 let i = e.currentTarget.dataset.index
 let that = this
 wx.showModal({
 title: ‘提示’,
 content: ‘确定要删除吗?’,
 cancelText: ‘取消’,
 confirmText: ‘确定’,
 success: res => {
 if (res.confirm) {
 that.data.imgList1.splice(i, 1);
 that.setData({
 imgList1:that.data.imgList1,
 pdfFile:‘’
 })
 }
 }
 })
 },
 DelImg2(e){
 console.log(e)
 let i = e.currentTarget.dataset.index
 let that = this
 wx.showModal({
 title: ‘提示’,
 content: ‘确定要删除吗?’,
 cancelText: ‘取消’,
 confirmText: ‘确定’,
 success: res => {
 if (res.confirm) {
 that.data.videoList1.splice(i, 1);
 that.setData({
 videoList1:that.data.videoList1,
 pdfFile:‘’
 })
 }
 }
 })
 },
 DelImg3(e){
 console.log(e)
 let i = e.currentTarget.dataset.index
 let that = this
 wx.showModal({
 title: ‘提示’,
 content: ‘确定要删除吗?’,
 cancelText: ‘取消’,
 confirmText: ‘确定’,
 success: res => {
 if (res.confirm) {
 that.data.fileList1.splice(i, 1);
 that.setData({
 fileList1:that.data.fileList1,
 pdfFile:‘’
 })
 }
 }
 })
 },
 previewImage(e){
 console.log(e)
 const current = e.currentTarget.dataset.url //获取当前点击的 图片 url
 let arr = []
 arr.push(current)
 wx.previewImage({
 current: current,
 urls: arr
 })
 },
 previewImg() {
 let img = this.pdfFile
 wx.downloadFile({
 url: img,
 success: function(res) {
 var Path = res.tempFilePath //返回的文件临时地址,用于后面打开本地预览所用
 wx.openDocument({
 filePath: Path,
 showMenu: true,
 success: function(a) {},
 fail: function(a) {
 wx.showToast({
 title: ‘文件打开失败’,
 icon: ‘none’,
 duration: 2000,
 })
 }
 })
 }
 })
 },
 uploadDIY(filePaths, successUp, failUp, i, length) {
 wx.showLoading({
 title: ‘上传中…’,
 })
 console.log(filePaths[i])
 let that = this
 wx.uploadFile({
 url: ‘https://www.xxxxx.com/mnp/oaapi/fileupload.php’,
 filePath: filePaths[i].path,
 name: ‘file’,
 formData: {
 ‘uid’: wx.getStorageSync(‘uid’),
 ‘token’: wx.getStorageSync(‘token’),
 },
 success: (res) => {
 const data = JSON.parse(res.data.replace(‘\uFEFF’,‘’))
 console.log(data)
 if (data.bs == ‘success’) {
 wx.showToast({
 title: data.errmsg,
 duration: 2000,
 icon: ‘success’
 })
 successUp++;
 // let arr = []
 // arr.push(‘https://xxxxx.oss-cn-shenzhen.aliyuncs.com/zhuangshi/zspdf.png’)
 let fileType = data.img.split(“.”)[data.img.split(“.”).length - 1]
 console.log(fileType,data.img)
 if(fileType == ‘pdf’|| fileType == ‘txt’|| fileType == ‘zip’|| fileType == ‘doc’|| fileType == ‘docx’ || fileType == ‘ppt’ || fileType == ‘pptx’ || fileType == ‘xls’ || fileType == ‘xlsx’ ){
 that.data.fileList1.push(data.img)
 that.setData({
 pdfFile:data.img,
 fileList1: that.data.fileList1
 })
 }else if(fileType == ‘jpg’|| fileType == ‘jpeg’ || fileType == ‘png’){
 that.data.imgList1.push(data.img)
 that.setData({
 pdfFile:data.img,
 imgList1: that.data.imgList1
 })
 }else if(fileType == ‘mp4’){
 that.data.videoList1.push(data.img)
 that.setData({
 pdfFile:data.img,
 videoList1: that.data.videoList1
 })
 }
 return
 that.data.imgList1.push(data.img)
 that.setData({
 pdfFile:data.img,
 imgList1: that.data.imgList1
 })
 that.data.pdfFile = data.img
 // console.log(‘上传图片成功:’, JSON.parse(res.data));
 // var data = JSON.parse(res.data);
 // console.log(data)
 // 把获取到的路径存入imagesurl字符串中
 // that.infolist[e].imglist.push(data.img)
 // console.log(this.data.imagesurl)
 } else if (data.bs == ‘guoqi’) {
 wx.showToast({
 title: data.errmsg,
 duration: 2000,
 icon: ‘error’
 })
 setTimeout(function() {
 wx.redirectTo({
 url: ‘…/…/pagesD/login/login’
 })
 }, 500)
 } else {
 wx.showToast({
 title: data.errmsg,
 duration: 2000,
 icon: ‘error’
 })
 }
  },
  fail: (res) => {
    failUp++;
  },
  complete: () => {
    i++;
    if (i == length) {
      // Toast('总共' + successUp + '张上传成功,' + failUp + '张上传失败!');
    } else { //递归调用uploadDIY函数
      that.uploadDIY(filePaths, successUp, failUp, i, length);
    }
  },
});
},
 uploadFileTap(e) {
 let that = this;
 wx.chooseMessageFile({
 count: 10,
 type: ‘all’,
 success(res) {
 console.log(res)
 // tempFilePath可以作为img标签的src属性显示图片
 const tempFilePaths = res.tempFiles
 // let fileType = tempFilePaths[0].type
 // that.setData({
 // fileType:fileType
 // })
 that.uploadDIY( res.tempFiles, 0, 0, 0, res.tempFiles.length,e);
 return
 wx.uploadFile({
 url: ‘https://www.xxx.com/mnp/oaapi/fileupload.php’,
 filePath: tempFilePaths[0].path,
 name: ‘file’,
 formData: {
 ‘uid’: wx.getStorageSync(‘uid’),
 ‘token’: wx.getStorageSync(‘token’),
 },
 success(res) {
 const data = JSON.parse(res.data.replace(‘\uFEFF’,
 ‘’))
 console.log(data)
 if (data.bs == ‘success’) {
 wx.showToast({
 title: data.errmsg,
 duration: 2000,
 icon: ‘success’
 })
 let arr = []
 arr.push(‘https://xxxxx.oss-cn-shenzhen.aliyuncs.com/zhuangshi/zspdf.png’)
 that.setData({
 pdfFile:data.img,
 imgList1:arr
 })
 that.data.pdfFile = data.img
        } else if (data.bs == 'guoqi') {
          wx.showToast({
            title: data.errmsg,
            duration: 2000,
            icon: 'error'
          })
          setTimeout(function () {
            // wx.removeStorageSync('userInfo'); //清除缓存
            // wx.removeStorageSync('uid')
            // wx.removeStorageSync('token')
            wx.redirectTo({
              url: '../index/index',
            })
          }, 500)
        } else {
          wx.showToast({
            title: data.errmsg,
            duration: 2000,
            icon: 'error'
          })
        }
      }
    })
  }
})
},
 /**
- 生命周期函数–监听页面加载
 */
 onLoad(options) {
 // console.log(cos)
 if (options.id) {
 this.setData({
 id: options.id
 })
 }
 },
 handleItem(e) {
 this.setData({
 itemname: e.detail.value
 })
 },
 handlebeizhu(e) {
 this.setData({
 beizhu: e.detail.value
 })
 },
 handlesave() {
 let that = this
 if (!this.data.itemname) {
 wx.showToast({
 title: ‘请填写项目名称’,
 icon: ‘error’,
 duration: 2000
 })
 return
 }
 wx.showLoading({
 title: ‘保存中…’,
 })
wx.request({
  url: app.globalData.siteurlh5 + '/fileadd.php',
  data: {
    id:this.data.id,
    beizhu:this.data.beizhu,
    uid: wx.getStorageSync('uid'),
    token: wx.getStorageSync('token'),
    title: this.data.itemname,
    img: this.data.videoList1.concat(this.data.fileList1, this.data.imgList1)
  },
  header: {
    'content-type': 'application/x-www-form-urlencoded'
  },
  method: 'POST',
  success(res) {
    console.log(res, )
    if (res.data.bs == 'success') {
      wx.showToast({
        title: res.data.errmsg,
        duration: 2000,
        icon: 'success'
      })
      setTimeout(() => {
        wx.navigateBack({
          delta: 1,
        })
      }, 2000);
    } else if (res.data.bs == 'failed') {
      wx.showToast({
        title: res.data.errmsg,
        duration: 2000,
        icon: 'error'
      })
    } else if (res.data.bs == 'error') {
      wx.showToast({
        title: res.data.errmsg,
        duration: 2000,
        icon: 'error'
      })
    } else if (res.data.bs == 'guoqi') {
      wx.removeStorageSync('userInfo'); //清除缓存
      wx.removeStorageSync('uid')
      wx.removeStorageSync('token')
      wx.redirectTo({
        url: '../index/index',
      })
    }
  },
  fail(err) {
    console.log(err)
    wx
  },
  complete() {
    // wx.hideLoading()
  }
})
},
/**
- 用户点击右上角分享
 */
 onShareAppMessage() {
}
 })



















