uniapp多格式文件选择(APP,H5)【补充】

uniapp多格式文件选择(APP,H5)【补充】

背景

之前写过一篇【uniapp多格式文件选择(APP,H5)】文章使用renderjs来实现H5端和APP端选择文件,当时文章中只涉及了如何选择文件,今天的文章作为补充来实现怎么将选择好的文件进行上传。

实现思路

上次我们能获取到blob格式的文件流,在H5端这个blob流可以直接通过uni.uploadFile相关的API进行上传,这种方案本来就是使用html端的dom实现,所以并无问题。但是在APP端的blob流上传则会报错。这里我们的思路是再renderjs视图层通过FileReader将文件转成base64,然后把选择的文件base64数据发送到逻辑层,逻辑层将base64转成一个path,这样就可以正式上传。

代码实现

思路上面已经有了,这里就直接上代码:

<template>
	<view class="content">
		<button @click="fileChoose">文件选择</button>
		<view :fileData="fileData" :change:fileData="renderJS.receiveFileData"/>
		<view style="word-break:break-all;">文件路径:{{filePath}}</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				fileData: '',
				filePath: '',
				fileName: ''
			}
		},
		onLoad() {
			
		},
		methods: {
			fileChoose(){
				this.fileData = 'test'
				setTimeout(()=> {
					this.fileData = ''
				},1000)
			},
			async receiveRenderFile(result){
			  // #ifdef APP-PLUS
			  const fileUrl = await this.base64toPath(result.filePath, result.name);
			  this.fileName = fileUrl.relativePath
			  this.filePath = fileUrl.localAbsolutePath
			  // #endif
			  // #ifdef H5
			  this.fileName = result.name
			  this.filePath = result.filePath
			  // #endif
			  console.log('选择文件的路径:'+this.filePath)
			},
			//将base64转成路径
			async base64toPath(base64, attachName) {
				console.log('base64开始转化成文件')
				let _that = this;
				return new Promise(function(resolve, reject) {
					const filePath = `_doc/yourFilePath/${attachName}`;
					plus.io.resolveLocalFileSystemURL('_doc', function(entry) {
						entry.getDirectory("yourFilePath", {
							create: true,
							exclusive: false,
						}, function(entry) {
							entry.getFile(attachName, {
								create: true,
								exclusive: false,
							}, function(entry) {
								entry.createWriter(function(writer) {
									writer.onwrite = function(res) {
										console.log('base64转化文件完成')
										const obj = {
											relativePath: filePath,
											localAbsolutePath: plus.io
												.convertLocalFileSystemURL(
													filePath)
										}
										resolve(obj);
									}
									writer.onerror = reject;
									writer.seek(0);
									writer.writeAsBinary(_that
										.getSymbolAfterString(base64,
											','));
								}, reject)
							}, reject)
						}, reject)
					}, reject)
				})
			},
			// 取某个符号后面的字符
			getSymbolAfterString(val, symbolStr) {
				if (val == undefined || val == null || val == "") {
					return "";
				}
				val = val.toString();
				const index = val.indexOf(symbolStr);
				if (index != -1) {
					val = val.substring(index + 1, val.length);
					return val;
				} else {
					return val
				}
			}
		}
	}
</script>
<script module="renderJS" lang="renderjs">
	export default {
		data() {
			return {}
		},
		mounted() {
			console.log('mounted')
		},
		methods: {
			receiveFileData(newValue, oldValue, ownerVm, vm){
				if(!newValue){
					return
				}
				this.createFileInputDom(ownerVm)
			},
			createFileInputDom(ownerVm){
				let fileInput = document.createElement('input')
				fileInput.setAttribute('type','file')
				fileInput.setAttribute('accept','*')
				fileInput.click()
				fileInput.addEventListener('change', e => {
					let file = e.target.files[0]
					// #ifdef APP-PLUS
					console.log('开始读取文件')
					let reader = new FileReader();
					//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
					reader.readAsDataURL(file);
					reader.onload = function(event) {
						const base64Str = event.target.result; // 文件的base64
						console.log('文件读取完成')
						//如果文件较大,这里调用到逻辑层可能时间较长
						ownerVm.callMethod('receiveRenderFile', {
							name: file.name,
							filePath: base64Str
						})
					}
					// #endif
					// #ifdef H5
					const filePath = URL.createObjectURL(file)
					ownerVm.callMethod('receiveRenderFile',{
						name: file.name,
						filePath: filePath
					})
					// #endif
				})
			}
		}
	}
</script>
<style>
</style>

运行结果

我们这里选择手机一个txt文件

在这里插入图片描述

查看打印日志
在这里插入图片描述
界面上选择结果
在这里插入图片描述

到这里拿到文件路径之后就可以上传了。

注意事项

这种方式因为要进行逻辑层和视图层通讯,在APP侧如果选择大文件可能会造成内存溢出或者等待时间过长的问题,请自行取舍。

尾巴

今天的文章就到这里了,希望能给大家帮助,如果喜欢我的文章,欢迎给我点赞,评论,关注,谢谢大家!

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值