美文网首页
taro + react hooks + oss小程序上传

taro + react hooks + oss小程序上传

作者: 月光一族 | 来源:发表于2022-11-16 16:44 被阅读0次

    最近在做一个新项目,用到了taro + react hooks + oss小程序上传。今天就来分享一下其中的技术,目前来看,taro+ react hooks做的小程序很多框架不兼容,尤其是UI框架,能够打包成功的很少。试了只有@nutui/nutui-react-taro 和 taro-ui@3.1.0-beta.2在小程序执行时打包成功,当然了,小程序只需要在微信开发者工具上传即可,不需要打包,之前在这里的纠结的原因是习惯了build,尴尬了。

    1、按照taro官方文档构建一个新项目,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、把需要调用的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下

    // 将一个对象转成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 ="未授权,请登录";

    break;

              }

    case 403:

    message ="没有权限,拒绝访问";

    break;

              case 404:

    message =`请求地址出错`;

    break;

              case 500:

    message ="服务器内部错误";

    break;

              case 501:

    message ="服务未实现";

    break;

              case 502:

    message ="网关错误";

    break;

              case 503:

    message ="服务不可用";

    break;

              case 504:

    message ="网关超时";

    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(), // 设置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, // 开发者服务器的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获取以及图片上传调用,在选完图片后会调用一次ossGetAccessUrl,可优化为进入首页调用,放在dva中缓存起来ossGetAccessUrl,考虑到oss的token可能会失效,所以我这里每次上传都调用一次

    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、在页面中引入调用

    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)

    }

    }

    })

    相关文章

      网友评论

          本文标题:taro + react hooks + oss小程序上传

          本文链接:https://www.haomeiwen.com/subject/zjwyxdtx.html