腾讯云 小程序 SDK对象存储 COS使用记录,原生小程序写法。

最近做了一个项目,需求是上传文档,文档类型多种,图片,视频,文件,doc,xls,zip,txt 等等,而且文档类型可能是大文件,可能得上百兆,甚至超过1G。

腾讯云文档地址:https://cloud.tencent.com/document/product/436/31953 腾讯云可以支持5G 的文件,还是很厉害的。

这里只要是讲一下使用这个SDK的流程,因为第一次看文档的时候,文档介绍很简洁,甚至有点笼统。我当时都是很懵的,无从下手。

这个是小程序小程序直传实践的实现步骤,同样使用于对象存储。,我们一开始研究SDK对象储存觉得很难,然后想简单点,搞个对象储存,不这么麻烦。最后是借鉴了这里的步骤思路。

1、登录后台创建桶,地域

2、获取秘钥

3、小程序配置白名单

核心代码就这么点,选择文件,将后缀传给服务器,服务器根据后缀,生成一个cos文件路径,计算对应的签名,返回URL和签名信息给前端。

最终效果

* 文件名称: * 备注: * 文件: 去上传文件 文件列表 {{item}} × 保 存

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 的文件,这里是不支持的。

![在这里插入图片描述](https

😕/img-blog.csdnimg.cn/c1ecbd1f015f43fdb7422f425223ffac.png)

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>

保 存 wxss 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: #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() {

}

})

相关推荐
DreamByte17 分钟前
Python Tkinter小程序
开发语言·python·小程序
说私域42 分钟前
开源 AI 智能名片小程序:开启内容营销新境界
人工智能·小程序
汇匠源1 小时前
零工市场小程序:保障灵活就业
java·小程序·零工市场
哈尔滨财富通科技1 小时前
家居小程序有什么用?
小程序
程序员阿龙1 小时前
【2025】基于微信小程序的网上点餐系统设计与实现、基于微信小程序的智能网上点餐系统、微信小程序点餐系统设计、智能点餐系统开发、微信小程序网上点餐平台设计
微信小程序·小程序·毕业设计·订单管理·在线点餐·订单跟踪·在线支付
张人玉19 小时前
微信小程序开发——比较两个数字大小
微信小程序·小程序
计算机学姐1 天前
基于微信小程序的食堂点餐预约管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
罗_三金1 天前
微信小程序读写NFC标签(实现NFC标签快速拉起小程序)实战
前端·javascript·微信小程序·小程序
双普拉斯1 天前
微信小程序实现转盘抽奖,可以自定义编辑奖项列表
javascript·微信小程序·小程序
说私域1 天前
开源 AI 智能名片链动 2+1 模式 O2O 商城小程序在社群活动中的应用与时机选择
人工智能·小程序