uni-app如何选择文件上传

文章介绍了如何在uniapp中利用renderjs绕过上传图片的限制,实现文件选择功能,包括创建input标签、监听change事件获取File对象、转换为base64并上传的详细步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于uni框架的限制,只能选择图片进行上传,那如果想要选择文件上传呢?

使用renderjs

uniapp中不能像h5那样获取操作生成DOM,在开发中就会碰到很多需要绕很多弯路才能解决的问题,但uniapp提供了renderjs来弥补这个缺陷

基本使用
<template>
	<button type="primary" size="mini" @tap="yourModule.onClick">选择文件</button>
</template>

// 注意,一定要使用选项式API
<script>
    export default {
        data(){
            return{
                
            }
        },
        methods:{
            
        }
    }
</script>
<script module="yourModule" lang="renderjs">
    export default {
        data(){
            return{
                
            }
        },
        methods:{
            onClick(){
                console.log('触发了yourModule的onClick方法')
            }
        }
    }
</script>

更多renderjs的使用方法请参考:renderjs使用方法

实现思路:

相信你已经基本熟悉了renderjs的使用方法,接下来介绍选择文件的具体思路

使用renderjs创建一个type为file的input标签,使用click方法触发选择,就可以选择文件,再监听input的onchange事件,获取到选择的文件File对象,再将其转成base64回发给数据层,在数据层使用plus的api将base64转成本地路径,有了本地路径是不是就好办多了?使用uni.uploadFile就能实现上传。话不多说直接上代码

<template>
	<button type="primary" size="mini" @tap="attchChoose.onClick">选择文件</button>
</template>
<script>
	import {
		API_SITE
	} from '@/config/config'
	import pop from '@/util/pop'
	import {
		uploadFile
	} from '@/common/request.js'


	export default {
		data() {
			return {
				
			}
		},
		methods: {
			async upload(path) {
				try {
					// pop.showLoading()
                    // 参数一:本地路径,参数二:后端对应字段名,我这里只是进行了简单的封装
					const result = await uploadFile(path,"files");
					console.log(result);
					// pop.showToast("上传成功")
				} catch (e) {
					console.log(e);
					// pop.showToast(e)
				}
			},
			async chooseFile(data) {
				try {
					const fileUrl = await this.base64toPath(data.base64Str, data.attachName);
					this.upload(fileUrl.localAbsolutePath)
				} catch (e) {
					console.log("err", e);
				}
			},
			/**
			 * @param {Object} base64 文件base64
			 * @param {Object} attachName //文件名需要后缀,如:张三.jpg
			 */
			async base64toPath(base64, attachName) {
				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) {
										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="attchChoose" lang="renderjs">
	let fileInputDom = null;
	export default {
		methods: {
			createFileInputDom() {
				fileInputDom = document.createElement("input");
				fileInputDom.setAttribute('type', 'file');
				fileInputDom.setAttribute('accept', '*');
			},
			onClick(event, ownerInstance) {
				if (!fileInputDom) {
					this.createFileInputDom();
				}
				fileInputDom.click(); // 模拟click
				fileInputDom.addEventListener('change', (e) => {
					fileInputDom = null;
					let choicesFiles = e.target.files[0];
					let reader = new FileReader();
					//读取图像文件 result 为 DataURL, DataURL 可直接 赋值给 img.src
					reader.readAsDataURL(choicesFiles);
					reader.onload = function(event) {
						const base64Str = event.target.result; // 文件的base64
						ownerInstance.callMethod('chooseFile', {
							attachName: choicesFiles.name,
							size: choicesFiles.size,
							base64Str,
						})
					}
					e.target.value = "";
				})
			}
		}
	}
</script>

亲测有效

<think>好的,我需要帮助用户解决在UniApp中使用plus.io.FileReader计算文件SHA256哈希值的问题。首先,我得理清用户的需求和环境。用户提到要在H5、小程序和APP环境下实现,但现在具体问的是APP环境下使用plus.io.FileReader的方法。 根据引用[2],FileReader对象可以用来读取文件,支持readAsDataURL和readAsText等方法。但SHA256计算可能需要文件的二进制数据,比如ArrayBuffer。不过,plus.io.FileReader的文档显示,它可能没有直接读取为ArrayBuffer的方法,可能需要用其他方式转换。 接下来,我需要考虑如何在APP端获取文件的ArrayBuffer。可能需要使用plus.io中的API来读取文件,比如通过plus.io.resolveLocalFileSystemURL获取文件对象,然后用FileReader读取。同时,引用[1]中提到在UniApp中读取文件的ArrayBuffer和计算SHA256,可能需要使用第三方库,比如crypto-js或者hash-wasm。 步骤大概是:选择文件,读取为ArrayBuffer,然后使用SHA256算法处理。但plus.io.FileReader是否有readAsArrayBuffer方法呢?根据引用[2],标准FileReader有readAsArrayBuffer,但plus.io的实现可能不同。可能需要用readAsDataURL读取,然后解码Base64得到二进制数据。 另外,引用[3]提到在APP端设置横屏,这可能和文件操作无关,但需要注意环境判断。用户需要在APP端使用plus.io的API,所以代码需要包裹在// #ifdef APP-PLUS中。 综合起来,可能的步骤是:使用plus.io选择文件,用FileReader读取为DataURL,提取Base64部分,将其转换为ArrayBuffer,然后使用crypto-js计算SHA256。需要注意Base64解码是否正确,以及性能问题,特别是大文件处理可能需要分块读取。 此外,需要考虑如何集成第三方库到UniApp项目中,比如通过npm安装或直接引入脚本。对于APP端,可能需要将库文件放在合适的目录,并正确引用。 最后,测试不同文件类型和大小,确保在不同环境下都能正确计算哈希值。同时处理可能出现的错误,比如文件读取失败或计算超时。</think>在UniApp中使用`plus.io.FileReader`计算文件SHA256哈希值,需结合文件读取和加密库实现。以下是具体实现步骤: ### 实现步骤 1. **选择文件** ```javascript // #ifdef APP-PLUS plus.io.chooseFile({ success: function(e) { const filePath = e.files[0].fullPath; calculateSHA256(filePath); } }); // #endif ``` 2. **读取文件内容** ```javascript function calculateSHA256(filePath) { const reader = new plus.io.FileReader(); reader.onloadend = function(evt) { // Base64数据转换为ArrayBuffer const base64 = evt.target.result.split(',')[1]; const raw = atob(base64); const arrayBuffer = new ArrayBuffer(raw.length); const uintArray = new Uint8Array(arrayBuffer); for (let i = 0; i < raw.length; i++) { uintArray[i] = raw.charCodeAt(i); } // 计算SHA256 const hash = CryptoJS.SHA256(CryptoJS.lib.WordArray.create(uintArray)); console.log('SHA256:', hash.toString()); }; reader.readAsDataURL(filePath); // 读取为DataURL格式 } ``` 3. **引入加密库** 在项目中引入`crypto-js`库: ```bash npm install crypto-js ``` 页面中引入: ```javascript import CryptoJS from 'crypto-js'; ``` ### 关键说明 1. `readAsDataURL`方法将文件转换为Base64格式,需通过`atob`解码获取二进制数据[^2] 2. 转换后的ArrayBuffer通过`CryptoJS.lib.WordArray.create`适配加密库 3.文件建议分块读取避免内存溢出 ### 注意事项 - 需在manifest.json中启用`"UniFFI": true`支持原生操作 - 超过10MB文件推荐使用`plus.io.File`分片读取 - 小程序环境需改用`wx.getFileSystemManager`API[^1]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值