当前位置:   article > 正文

微信小程序使用webview实现文件上传功能_小程序上传文件 uniapp 上传文件 webview

小程序上传文件 uniapp 上传文件 webview

微信小程序使用webview实现文件上传功能(uni-app)

项目开发了一个批示单的功能,用户填写批示单信息要上传正文及附件(多文件上传,有需要可在文章末尾查看),上传文件功能原调用的是uni.chooseMessageFile方法选择聊天记录中文件。

问题:用户在电脑端打开小程序后发现选择文件按钮点击无反应。
百度后发现此方法电脑端无法使用,并且微信平台暂时没有具体方法,有网上小伙伴说用webview结合input实现。

具体实现:
原设计:A页面选择添加文件后提交
修改后:添加一个B页面(upload文件),在B页面引入webview
A页面跳转到 ===> B页面 接入webview ===> webview(html)使用input选择文件 文件获取后postMessage并返回,具体代码如下

B页面(uploadFile.vue)

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

uploadFile.html

创建一个文件夹用来存放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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173

在这里插入图片描述

A页面

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()
			}
		})
	},
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

转换为base64时报错,删除base64 中开头的 data:xxx/xxx;base64, 即可
将base64格式图片转化为临时路径时报错
测试完成后,将html页面及相关文件上传至服务器,并在微信开放平台中进行配置 开发==>开发管理==>业务域名
配置webview业务域名

多文件上传

微信小程序实现多文件同时上传

本文基于以下文章所写:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/262798
推荐阅读
相关标签
  

闽ICP备14008679号