雲函數開發遇到的問題
在微信雲開發環境當中,普通的使用者并沒有往雲存儲内寫入檔案的權限
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuEmdxYGbtVHczQzLcJDM2ITO2EzLcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
是以普通使用者想要使用wx.cloud.uploadFile顯然是不現實的
但是我們同時也知道,雲函數是背景服務端,具有管理者權限,隻要能調用雲函數上傳檔案就可以解決這個問題了
參照官方文檔中雲函數的寫法
const cloud = require('wx-server-sdk')
const fs = require('fs')
const path = require('path')
exports.main = async (event, context) => {
const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg'))
return await cloud.uploadFile({
cloudPath: 'demo.jpg',
fileContent: fileStream,
})
}
複制
官方文檔寫的雲裡霧裡,并不是這麼容易了解
_dirname代表的是檔案根目錄,官方文檔能實作的功能貌似隻是移動雲存儲空間中的檔案,并不能操作本地檔案
解決方案
隻上傳檔案路徑是不能把本地檔案成功上傳到雲存儲的,但是我們可以将本地檔案進行 進制 編碼 轉化為位元組流上傳到雲函數中,
再在雲函數的操作中把位元組或檔案轉化為相對應的格式
微信小程式文檔為我們提供了一個很好的用于編碼檔案的功能函數
wx.getFileSystemManager()
利用這個函數,可以把圖檔編碼成為base64 的形式上傳到雲函數
如果是多個圖檔上傳,隻需要周遊即可
wx.getFileSystemManager().readFile({
filePath: that.data.images[i], //選擇圖檔傳回的相對路徑
encoding: 'base64', //編碼格式
success: res => { //成功的回調
wx.cloud.callFunction({
name:'file',
data:{
path: 'pictures/' + util.vcode(new Date())+index+'.png',
file: res.data
},
success(_res){
console.log(_res)
},fail(_res){
console.log(_res)
}
})
index++;
}
})
複制
其中index的作用是對圖檔進行區分編碼,有不同的名字,不然重名的檔案上傳,原檔案會被覆寫
完整的js檔案
import {
promisify
} from '../../utils/promise.util'
import {
$init,
$digest
} from '../../utils/common.util'
var util = require('../../utils/util.js')
const wxUploadFile = promisify(wx.uploadFile)
const db = wx.cloud.database()
Page({
data: {
titleCount: 0,
contentCount: 0,
content: '',
images: []
},
onLoad(options) {
$init(this)
},
handleTitleInput(e) {
const value = e.detail.value
this.data.title = value
this.data.titleCount = value.length
$digest(this)
},
handleContentInput(e) {
const value = e.detail.value
this.data.content = value
this.data.contentCount = value.length
$digest(this)
},
chooseImage(e) {
wx.chooseImage({
count: 3,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: res => {
const images = this.data.images.concat(res.tempFilePaths)
this.data.images = images.length <= 3 ? images : images.slice(0, 3)
$digest(this)
}
})
},
removeImage(e) {
const idx = e.target.dataset.idx
this.data.images.splice(idx, 1)
$digest(this)
},
handleImagePreview(e) {
const idx = e.target.dataset.idx
const images = this.data.images
wx.previewImage({
current: images[idx],
urls: images,
})
},
submitForm(e) {
var that = this;
var index = 0;
var len = that.data.images.length;
wx.showLoading({
title: '上傳中...',
})
for(var i = 0; i < len ; i++)
{
console.log(i)
wx.getFileSystemManager().readFile({
filePath: that.data.images[i], //選擇圖檔傳回的相對路徑
encoding: 'base64', //編碼格式
success: res => { //成功的回調
wx.cloud.callFunction({
name:'file',
data:{
path: 'pictures/' + util.vcode(new Date())+index+'.png',
file: res.data
},
success(_res){
console.log(_res)
wx.hideLoading()
//wx.hideLoading()
},fail(_res){
console.log(_res)
}
})
index++;
}
})
}
}
})
複制
其中 $digest(this) 與 $init(this) 是setData的封裝寫法
詳細内容如下
微信小程式開發工具包--> Gitee
至于想用什麼方式儲存 傳回的檔案 id 取決于自己
雲函數的寫法
// 雲函數入口檔案
const cloud = require('wx-server-sdk')
const fs = require('fs')
const path = require('path')
cloud.init({
env: 'kindear-fd77cd'
})
exports.main = async (event, context) => {
try{
return await cloud.uploadFile({
cloudPath: event.path,
fileContent: new Buffer(event.file, 'base64')
})
}catch(e){
return e;
}
}
複制
其中,必須強調的是cloud.init 必須重新确定下環境id
不然上傳的檔案或者圖檔并不在小程式初始化的環境中
雲函數實作效果
圖檔送出界面如圖所示
點選送出
在雲存儲中檢視
成功上傳
一種雲存儲檔案名稱的編碼方式
基本方式在js檔案中已經有具體描述,通過具體到秒的時間 和 圖檔的上傳順序進行編碼 基本可以保證不會有重名的檔案存在
現在給出時間的編碼方式
function vcode(date)
{
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('_') + '_'+[hour, minute, second].map(formatNumber).join('_')
}
複制