天天看點

小程式雲開發--雲函數上傳檔案或圖檔 base64

雲函數開發遇到的問題

在微信雲開發環境當中,普通的使用者并沒有往雲存儲内寫入檔案的權限

小程式雲開發--雲函數上傳檔案或圖檔 base64

是以普通使用者想要使用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

不然上傳的檔案或者圖檔并不在小程式初始化的環境中

雲函數實作效果

小程式雲開發--雲函數上傳檔案或圖檔 base64

圖檔送出界面如圖所示

點選送出

小程式雲開發--雲函數上傳檔案或圖檔 base64

在雲存儲中檢視

成功上傳

小程式雲開發--雲函數上傳檔案或圖檔 base64

一種雲存儲檔案名稱的編碼方式

基本方式在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('_')
}           

複制