taro + react hooks + oss小程序上傳

最近在做一個新項目,用到了taro + react hooks + oss小程序上傳。今天就來分享一下其中的技術(shù),目前來看,taro+ react hooks做的小程序很多框架不兼容,尤其是UI框架,能夠打包成功的很少。試了只有@nutui/nutui-react-taro 和?taro-ui@3.1.0-beta.2在小程序執(zhí)行時打包成功,當然了,小程序只需要在微信開發(fā)者工具上傳即可,不需要打包,之前在這里的糾結(jié)的原因是習慣了build,尷尬了。

1、按照taro官方文檔構(gòu)建一個新項目,config配置添加別名配置如下:

alias: {

'@': path.resolve(__dirname, '..', 'src'),

? '@/images': path.resolve(__dirname, '..', 'src/images'),

? '@/assets': path.resolve(__dirname, '..', 'src/assets'),

? '@/components': path.resolve(__dirname, '..', 'src/components'),

? //'@/constants': path.resolve(__dirname, '..', 'src/constants'),

//'@/reducers': path.resolve(__dirname, '..', 'src/reducers'),

? '@/common': path.resolve(__dirname, '..', 'src/common'),

? '@/utils': path.resolve(__dirname, '..', 'src/utils')

},

2、把需要調(diào)用的api封裝在src/api

import { toQueryString }from '@/utils/filter'

import service from '@/utils/request';

//特殊請求加上這段編碼

const otherHeader = {'Content-Type':'application/x-www-form-urlencoded', 'Accept':'*/*' }

//獲取oss的信息

export const ossGetAccessUrl = (params, headers) => {

return service({

method:'GET',

? ? url:'/oss/token',

? ? data: params,

? ? headers: headers

})

}

3、把全局主題色封裝在common/theme.scss下

@charset "UTF-8";

//默認全局背景主題色!default

$default-background:#F6F6F7;

//默認字體、按鈕背景主題色

$default-primary:#52A86A;

4、把全局組件封裝在components下

5、把需要過濾的封裝在utils/filter下

// 將一個對象轉(zhuǎn)成QueryString

export const toQueryString = (obj) => {

if (!obj)return "";

? ? return cleanArray(

Object.keys(obj).map(key => {

if (obj[key] ===undefined)return "";

? ? ? ? ? ? return encodeURIComponent(key) +"=" +encodeURIComponent(obj[key]);

? ? ? ? })

).join("&");

}

6、把請求攔截封裝在utils/request

import Taro from '@tarojs/taro'

const baseURL ='https://xxx.xxx.com/'

let token ='xxxxxxxx'

let flag =true;

export const service = (parmas) => {

parmas.headers['token'] = token;

? let result =new Promise((resolve, reject) => {

Taro.request({

url: baseURL + parmas.url,?

? ? ? data: parmas.parmas,

? ? ? method:parmas.method ,

? ? ? header: {

...{

'content-type':'application/json' // 默認值

? ? ? ? }, ...parmas.headers

? ? ? },

? ? ? success:function (response) {

if (response.statusCode && response.statusCode !==200) {

if (flag) {

Taro.showToast({

title:JSON.stringify(response.data.message),

? ? ? ? ? ? ? icon:'none'

? ? ? ? ? ? })

flag =false;

? ? ? ? ? ? setTimeout(() => {

flag =true;

? ? ? ? ? ? }, 1000)

}

}

if (response.statusCode ===200) {

resolve(response.data)

}else {

reject();

? ? ? ? }

},

? ? ? fail(e:any) {

let message ="";

? ? ? ? switch (e.status) {

case 400:

message ="請求錯誤";

break;

? ? ? ? ? case 401: {

message ="未授權(quán),請登錄";

break;

? ? ? ? ? }

case 403:

message ="沒有權(quán)限,拒絕訪問";

break;

? ? ? ? ? case 404:

message =`請求地址出錯`;

break;

? ? ? ? ? case 500:

message ="服務(wù)器內(nèi)部錯誤";

break;

? ? ? ? ? case 501:

message ="服務(wù)未實現(xiàn)";

break;

? ? ? ? ? case 502:

message ="網(wǎng)關(guān)錯誤";

break;

? ? ? ? ? case 503:

message ="服務(wù)不可用";

break;

? ? ? ? ? case 504:

message ="網(wǎng)關(guān)超時";

break;

? ? ? ? ? case 505:

message ="HTTP版本不受支持";

break;

? ? ? ? ? default:

break;

? ? ? ? }

if (flag) {

Taro.showToast({

title: message,

? ? ? ? ? ? icon:'none'

? ? ? ? ? })

flag =false;

? ? ? ? ? setTimeout(() => {

flag =true;

? ? ? ? ? }, 1000)

}

reject(e)

}

})

})

return result;

}


下面來講封裝小程序上傳圖片到oss,因為小程序上傳的圖片與h5或web端不一樣,沒有file的概念,就需要看阿里云文檔踩坑

1、封裝stsToken,需要通過加密等方式得到signature,policy,x-oss-security-token

import cryptofrom 'crypto-js';

import {Base64}from 'js-base64';

// 計算簽名。

function computeSignature(accessKeySecret, canonicalString) {

return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));

}

const date =new Date();

date.setHours(date.getHours() +1);

const policyText = {

expiration: date.toISOString(), // 設(shè)置policy過期時間。

? conditions: [

// 限制上傳大小。

? ? ["content-length-range", 0, 1024 *1024 *1024],

? ],

};

export const getFormDataParams =async (credentials) => {

const policy = Base64.encode(JSON.stringify(policyText))// policy必須為base64的string。

? const signature =computeSignature(credentials.AccessKeySecret, policy)

const formData = {

OSSAccessKeyId: credentials.AccessKeyId,

? ? signature,

? ? policy,

? ? 'x-oss-security-token': credentials.SecurityToken

? }

return formData

}

2、封裝Taro.uploadFile上傳方法,傳入host、signature、OSSAccessKeyId、policy、key、filePath

import Taro from "@tarojs/taro";

export const wxUpload = (data) => {

const host = data.host;

? const signature = data.signature;

? const ossAccessKeyId = data.OSSAccessKeyId;

? const policy = data.policy;

? const key = data.key;

? const securityToken = data['x-oss-security-token'];

? const filePath = data.filePath; // 待上傳文件的文件路徑。

? let result =new Promise((resolve, reject) => {

Taro.uploadFile({

url: host, // 開發(fā)者服務(wù)器的URL。

? ? ? filePath: filePath,

? ? ? name:'file', // 必須填file。

? ? ? formData: {

name: filePath,

? ? ? ? key,

? ? ? ? policy,

? ? ? ? OSSAccessKeyId: ossAccessKeyId,

? ? ? ? signature,

? ? ? ? success_action_status:"200",

? ? ? ? 'x-oss-security-token': securityToken// 使用STS簽名時必傳。

? ? ? },

? ? ? success: (res) => {

console.log(res)

if (res.statusCode ===200) {

Taro.showToast({title:'上傳成功', icon:'none'})

resolve(host +'/' + key);

? ? ? ? }

},

? ? ? fail: err => {

reject(null)

Taro.showToast({title:'上傳失敗', icon:'none'})

return null;

? ? ? }

});

? })

return result;

}

3、封裝osstoken獲取以及圖片上傳調(diào)用,在選完圖片后會調(diào)用一次ossGetAccessUrl,可優(yōu)化為進入首頁調(diào)用,放在dva中緩存起來ossGetAccessUrl,考慮到oss的token可能會失效,所以我這里每次上傳都調(diào)用一次

import {randomString, filterUTCNo}from './filter'

import OSS from 'ali-oss';

import Taro from "@tarojs/taro";

import {getFormDataParams}from './sts'

import {wxUpload}from './wxUpload'

import {ossGetAccessUrl}from '@/api/home'

class MyUploadAdapterAll {

constructor(params) {

// 要在上載期間使用的文件加載器實例

? ? this.file = params.file

? ? this.ossGetAccessUrlData = {}

}

async getAccessUrl() {

if (!this.file) {

return

? ? }

try {

Taro.showLoading()

let res =await ossGetAccessUrl({}, {})

Taro.hideLoading()

if (res.code ===200) {

? ? ? ? let dataParams:any =await getFormDataParams({

AccessKeySecret: res.data.accessKeySecret,

? ? ? ? ? AccessKeyId: res.data.accessKeyId,

? ? ? ? ? SecurityToken: res.data.securityToken,

? ? ? ? })

dataParams.key =`${filterUTCNo(new Date())}/${randomString(8)}_${Date.now()}.${this.file.split('.')[this.file.split('.').length -1]}`

? ? ? ? dataParams.host ='https://' + res.data.bucket +'.' + res.data.endPoint.split('//')[1];

? ? ? ? dataParams.filePath =this.file;

? ? ? ? console.log(dataParams)

return await wxUpload(dataParams);

? ? ? }

}catch (e) {

? ? ? console.log(e)

}

}

}

export default MyUploadAdapterAll

4、在頁面中引入調(diào)用

import MyUploadAdapterAllfrom "@/utils/uploadAll";

Taro.chooseImage({

count:1, // 默認9

? sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,默認二者都有

? sourceType: ['album', 'camera'], // 可以指定來源是相冊還是相機,默認二者都有,在H5瀏覽器端支持使用 `user` 和 `environment`分別指定為前后攝像頭

? success:async (res) => {

console.log(res)

const myUploadAdapter =new MyUploadAdapterAll({

dir:'dev',

? ? ? file: res.tempFilePaths[0]

})

let url:string =await myUploadAdapter.getAccessUrl()

if (url) {

console.log(url)

}

}

})

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容