赞
踩
项目开发了一个批示单的功能,用户填写批示单信息要上传正文及附件(多文件上传,有需要可在文章末尾查看),上传文件功能原调用的是uni.chooseMessageFile方法选择聊天记录中文件。
问题:用户在电脑端打开小程序后发现选择文件按钮点击无反应。
百度后发现此方法电脑端无法使用,并且微信平台暂时没有具体方法,有网上小伙伴说用webview结合input实现。
具体实现:
原设计:A页面选择添加文件后提交
修改后:添加一个B页面(upload文件),在B页面引入webview
A页面跳转到 ===> B页面 接入webview ===> webview(html)使用input选择文件 文件获取后postMessage并返回,具体代码如下
<template> <view> <!-- 测试完成后改为线上地址 --> <web-view src="http://127.0.0.1:5500/%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6/uploadFile.html" @message="handleMessage"></web-view> </view> </template> <script> export default { methods: { handleMessage(e) { console.log('接收到的消息:' + JSON.parse(e.detail.data)); uni.setStorageSync('fileMsg', JSON.parse(e.detail.data)) } } } </script>
创建一个文件夹用来存放webview资源(uploadFile.html是在小程序中接入,本地测试时用vscode打开文件,使用live Serve创建一个本地服务,将服务地址复制放在B页面webview的src中)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>上传文件</title> <style> .uploadFilePage { display: flex; flex-direction: column; align-items: center; } .inputBox { width: 320px; height: 220px; color: #228EFF; font-size: 18px; margin-top: 100px; border: 1px dashed #228EFF; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; } .inputBox img { width: 130px; height: 130px; margin-bottom: 15px; } .inputBox .tips { font-size: 12px; color: #666; line-height: 30px; } .fileInput { display: none; } .fileList { line-height: 35px; margin-top: 20px; } .fileList .fileOne { display: flex; align-items: center; } .fileList .deleteIconBox { width: 50px; height: 35px; display: flex; align-items: center; justify-content: center; } .fileList .deleteIconBox img { width: 26px; height: 26px; } .goBackBtn { width: 120px; height: 45px; line-height: 45px; text-align: center; background-color: #228EFF; border-radius: 6px; color: #fff; margin-top: 35px; } .alert { position: fixed; top: 40%; left: 50%; transform: translate(-50%, -50%); padding: 10px; background-color: #faa734; color: #fff; border-radius: 6px; } </style> <!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 --> <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.4.0.js"></script> <!-- uni 的 SDK,必须引用。 --> <script type="text/javascript" src="//js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js"></script> <script src="./vue.min.js"></script> </head> <body> <div class="uploadFilePage" id="app"> <div class="inputBox" @click="makeFileInputClick"> <img src="./image/uploadIcon.png" alt=""> <div class="text">点击上传</div> <div class="tips">* 文件大小限制为10MB</div> <input type="file" class="fileInput" name="222" @change="chooseFile" ref="fileInput"> </div> <div class="fileList"> <div v-for="(item, index) in filesList.basicData" :key="index" class="fileOne">{{item.name}} 上传成功 <div class="deleteIconBox" @click="deleteFile(index)"><img src="./image/deleteIcon.png" alt=""> </div> </div> </div> <div @click="goBack" class="goBackBtn">完成</div> <div class="alert" v-show="isShowAlert">文件大小超过限制,请重新上传</div> </div> <script> console.log(Vue); new Vue({ el: '#app', data: { filesList: { basicData: [], // 原始数据 handledData: [] // 转化为base64的数据 }, isShowAlert: false }, methods: { makeFileInputClick() { this.$refs.fileInput.click() }, // 文件转base64 fileToBase64(file) { return new Promise(function (resolve, reject) { var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { typeof reader.result === 'string' && resolve(reader.result) || reject(); }; reader.onerror = function (error) { return reject(error); }; }); }, async chooseFile(e) { let fileList = this.$refs.fileInput.files for (const item of fileList) { // 限制文件大小 if (item.size / 1024 / 1024 > 10) { this.isShowAlert = true; setTimeout(() => { this.isShowAlert = false; }, 2500) return } this.filesList.basicData.push(item); this.filesList.handledData.push({ name: item.name, file: await this.fileToBase64(item) }); } }, deleteFile(index) { this.filesList.basicData.splice(index, 1) this.filesList.handledData.splice(index, 1) }, goBack() { uni.postMessage({ data: JSON.stringify(this.filesList.handledData) }); uni.navigateBack() } } }) </script> </body> </html>
onShow() { if (!uni.getStorageSync('fileMsg')) return let fileMsg = uni.getStorageSync('fileMsg'); uni.removeStorageSync('fileMsg'); fileMsg.forEach(item => { item.file = item.file.split('base64,')[1] // 不加此句是报了下图的错误,百度后是由于base64,及之前的原因,删除之后就不报错了 this.base64ToTempFilePath(item.name, item.file, (tempFilePath) => { console.log('转换成功,临时地址为:', tempFilePath) // 自己的业务逻辑... }, function() { uni.showToast({ title: '文件转换失败,请重试', icon: 'none' }) }) }) }, methods:{ base64ToTempFilePath(fileName, base64Data, success, fail) { const fs = uni.getFileSystemManager() // const fileName = 'temp_image_' + Date.now() + '.png' // 自定义文件名,可根据需要修改 const filePath = uni.env.USER_DATA_PATH + '/' + fileName const buffer = uni.base64ToArrayBuffer(base64Data) fs.writeFile({ filePath, data: buffer, encoding: 'binary', success() { success && success(filePath) }, fail() { fail && fail() } }) }, }
转换为base64时报错,删除base64 中开头的 data:xxx/xxx;base64, 即可
测试完成后,将html页面及相关文件上传至服务器,并在微信开放平台中进行配置 开发==>开发管理==>业务域名
多文件上传
本文基于以下文章所写:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。