uni.chooseImage失效

uni.chooseImage失效

环境:uni-app开发H5项目,H5项目链接webview嵌入app中
原因:webview中不支持,需要由APP进行原生支持
方案:由APP原生支持返回base64编码,处理base64编码后进行OSS上传实现拍照/选照上传功能

1.相关方法

// oss.js
import crypto from 'crypto-js';
import { Base64 } from 'js-base64'; // 计算签名

// 生成签名
function computeSignature(accessKeySecret, canonicalString) {
    return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}

// 构造OSS相关参数
export function getFormDataParams({ accesskeyid, accesskeysecret, securitytoken }) {
    if (accesskeyid && accesskeysecret && securitytoken) {
        const date = new Date();
        date.setHours(date.getHours() + 1);
        const policyText = {
            expiration: date.toISOString(),
            // 设置policy过期时间。
            conditions: [
                // 限制上传大小。
                ['content-length-range', 0, 1024 * 1024 * 1024]
            ]
        };
        const policy = Base64.encode(JSON.stringify(policyText)); // policy必须为base64的string。
        const signature = computeSignature(accesskeysecret, policy);
        const host= 'https://display-image.oss-cn-hangzhou.aliyuncs.com/'
        const formData = {
            OSSAccessKeyId: accesskeyid,
            signature,
            policy,
            'x-oss-security-token': securitytoken,
            host
        };
        return formData;
    }

    return null;
}

// base64编码转文件
export function base64ToFile(base64, filename) {
    if (!base64) {
        return null
    }
    const arr = base64.split(',')
    if (!arr.length || !arr[0]) {
        return null
    }
    // .match(/:(.*?);/)[1]
    const mimeMatcher = (arr[0]).match(/:(.*?);/)
    if (!mimeMatcher) {
        return null
    }
    const mime = mimeMatcher[1]
    const bstr = atob(arr[1])
    let n = bstr.length
    const u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr], filename, { type: mime })
}

// 获取文件名
export function getExtName(filePath) {
    return filePath.slice(filePath.lastIndexOf('.'))
}

2.触发拍照/选照

async uploadCoverImage(evt) {
    // #ifdef H5
    this.setData({
        callback: async(resp) => {
            // resp为处理后返回数据,设置回调可用于处理上传成功后的文件
        }
    })
    this.onShowPhoto(evt)
    // #endif
},

onShowPhoto(evt) {
    this.setData({
        photoShow: true, // 控制动作列表显隐
        photoEvent: evt
    })
},

onSelectPhoto(event) {
    let type = "1"
    if(event.detail.name == '拍摄') type = "0"
    this.getImage(type)
},

3.利用原生APP支持的API获取图片的base64编码

getImage(type) {
    let _this = this
    let config = {
        // API对应参数
    }
    window.xtion.getPhoto(config, function(res, error){
        if(error != null) {
            uni.showToast({
                title: '无法上传',
                icon: 'error'
            });
        }
        // 获取图片数据
        if(res.length === 0) {
            uni.showToast({
                title: '未选择照片',
                icon: 'error'
            });
        }
        else {
            _this.uploadImage(res[0])
        }
    })
},

4.处理base64编码返回图片

uploadImage(evt, cb) {
    // #ifdef H5
    uni.showLoading({
        title: '上传中...'
    });
    this.handleSelectFilesChange({
        file: base64ToFile(evt.file, getExtName(evt.filePath)),
        base64: evt.file
    })
    // #endif
}

 handleSelectFilesChange(e) {
    const selectedFile = e.file
    const base64 = e.base64
    if (!selectedFile) return
    this.uploadFile(selectedFile)
        .then((res) => {
            this.callback(res) // 上传成功触发回调的后续处理
        })
        .catch(error => {
            this.callback({
                status: 'fail',
                filePath: base64, // 图片base64编码
                imgUrl: '' // 图片远程路径
            })
        })
},

5.OSS上传图片

// 获取OSS上传相关参数
async getUploadConfig() {
    const resp = await getOssParams();
    console.log('upload params:', resp);

    if (resp?.resp_data) {
        const config = getFormDataParams(resp?.resp_data);

        if (config) {
            this.setData({
                uploadConfig: config
            });
        }
    }
},

async uploadFile(file) {
    const uid = guid()
    const dateTime = new Date()
    const url = uid
    const tenantCode = uni.getStorageSync('tenantcode') || '1101190'
    const objectKey = `${url.substr(0, 3)}/img/${dateTime.getFullYear()}${dateTime.getMonth() + 1}${dateTime.getDate()}/${tenantCode}/${url}.jpg`
    const config = this.uploadConfig

    // 构建上传formData
    let formData = new FormData()
    formData.append('key',objectKey)
    formData.append("policy",config.policy)
    formData.append("OSSAccessKeyId",config.OSSAccessKeyId)
    formData.append('x-oss-security-token',config['x-oss-security-token'])
    formData.append("signature",config.signature)
    formData.append("file",file)

    // 开始上传
    try {
        let res = await http({
            method:'post',
            url: config.host,
            headers: { 'Content-Type': 'multipart/form-data' },
            data:formData
        })
        console.log('成功提交:', res)
        const imgUrl = `${config.host}${objectKey}`;
        return {
            status: 'success',
            filePath: imgUrl,
            imgUrl,
            file
        }
    } catch (e) {
        console.log('error: ', e)
        throw Error(e)
    }
},
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值