UniApp 在手机端(Android)打开选择文件和文件写入

复制代码
<!-- 文件选择组件 -->
<template>
	<view>
		<view @click="handleSelectFile"> <!-- 指定一个默认插槽sss -->
			<slot>选择文件</slot>
		</view>
		<view id="fileSelectContainer" :prop="fileProps" :change:prop="fileSelectModule.updateFileProps" r-entry />
	</view>
</template>
<!-- 逻辑层 -->
<script>
	export default {
		name: "FileSelect",
		components: {},
		data() {
			return {
				fileProps: {
					acceptTypes: '.xls,.xlsx',
					selectFileTrigger: false,
					fileStrType: 'Base64' //Base64、String
				}
			}
		},
		onLoad() {},
		methods: {
			handleUniSelectFile() {
				uni.chooseImage({
					count: 6, //默认9
					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
					sourceType: ['album'], //从相册选择
					success: function(res) {
						console.log("uni.chooseImage", res);
						console.log(JSON.stringify(res.tempFilePaths));
					}
				});
			},
			updataSelectFileTrigger(selectFileTrigger) {
				this.fileProps.selectFileTrigger = selectFileTrigger
			},
			handleSelectFile() { //选择文件按钮
				//通过属性改变,配合模块的:change:prop=触发视图层的事件
				this.fileProps.selectFileTrigger = true;
			},
			// 处理文件选择回调
			handleFileSelected(files) {
				this.$emit("fileChange", files)
			},
		}
	}
</script>
<!--视图层:使用 RenderJS模块方式进行APP上非图片和视频选择 -->
<script module="fileSelectModule" lang="renderjs">
	export default {
		data() {
			return {
				fileInputId: "select-file-input",
				fileInput: null,
				fileStrType: null //Base64、String
			};
		},
		mounted() {
			this.createFileInput(); // 动态创建文件输入元素
			console.log('FileSelectModule已挂载');
		},
		methods: {
			createFileInput() { // 创建文件输入元素
				const existingInput = document.getElementById(this.fileInputId);
				if (existingInput) { // 移除已存在的input元素
					existingInput.remove();
				}
				// 创建新的文件输入元素
				this.fileInput = document.createElement('input');
				this.fileInput.id = this.fileInputId;
				this.fileInput.type = 'file';
				this.fileInput.style.display = 'none';

				// 添加文件选择事件监听
				this.fileInput.addEventListener('change',
					(event) => {
						this.handleFileChange(event);
					});
				document.body.appendChild(this.fileInput);
			},

			handleFileChange(event) { // 文件选择文成
				const files = event.target.files;
				if (!files) return;
				let promiseArr = []
				for (let file of files) {
					promiseArr.push(this.fileToBase64OrStr(file))
				}
				Promise.all(promiseArr)
					.then(values => {
						let tempFilePaths = [];
						let tempFiles = []
						for (let fileInfo of values) {
							tempFilePaths.push(fileInfo.path)
							tempFiles.push(fileInfo)
						}
						let result = {
							tempFilePaths,
							tempFiles
						}
						this.$ownerInstance.callMethod('handleFileSelected', result);
					})
					.catch(err => {
						console.log(err);
					})
			},
			triggerFileInput() { // 触发文件输入点击
				if (this.fileInput) {
					this.fileInput.click(); //触发点击事件,进行文件选择
					this.$ownerInstance.callMethod("updataSelectFileTrigger", false) //重置文件选择标识方便下次进行选择
				}
			},
			updateFileProps(newValue, oldValue) { // 更新文件属性
				if (newValue && newValue.selectFileTrigger) { // 监听文件选择触发信号
					this.fileStrType = newValue.fileStrType || "String"
					this.triggerFileInput();
				}
			},
			fileToBase64OrStr(file) { //将文件转场base64
				return new Promise((resolve, reject) => {
					const reader = new FileReader()
					reader.onloadend = () => { //文件读取操作完成时的回调函数
						const base64String = reader.result
						let result = {
							path: base64String,
							size: file.size,
							name: file.name, //这个属性uni.chooseImage中没有
							type: file.type //这个属性uni.chooseImage中没有
						}
						resolve(result)
					}
					reader.onerror = (e) => {
						reject(3)
					}
					//Base64、String
					if ("Base64" === this.fileStrType) {
						reader.readAsDataURL(file) //以URL编码(Base64编码)格式读取文件数据内容
					} else {
						reader.readAsText(file) //以文本格式读取文件数据内容
					}
				})
			}
		}
	};
</script>
<style>
</style>

打开文件选择框截图

相关推荐
一心赚狗粮的宇叔4 分钟前
03.Node.js依赖包补充说明及React&Node.Js项目
前端·react.js·node.js
子春一6 分钟前
Flutter for OpenHarmony:音律尺 - 基于Flutter的Web友好型节拍器开发与节奏可视化实现
前端·flutter
JarvanMo6 分钟前
150万开发者“被偷家”!这两款浓眉大眼的 VS Code 插件竟然是间谍
前端
亿元程序员8 分钟前
大佬,现在AI游戏开发教程那么多,你不搞点卖给大学生吗?
前端
未来龙皇小蓝19 分钟前
RBAC前端架构-02:集成Vue Router、Vuex和Axios实现基本认证实现
前端·vue.js·架构
黄林晴22 分钟前
Android 17 再曝猛料:通知栏和快捷设置终于分家了,这操作等了十年
android
晓得迷路了32 分钟前
栗子前端技术周刊第 116 期 - 2025 JS 状态调查结果、Babel 7.29.0、Vue Router 5...
前端·javascript·vue.js
有位神秘人44 分钟前
Android获取设备中本地音频
android·音视频
顾北121 小时前
AI对话应用接口开发全解析:同步接口+SSE流式+智能体+前端对接
前端·人工智能
JMchen1231 小时前
Android网络安全实战:从HTTPS到双向认证
android·经验分享·网络协议·安全·web安全·https·kotlin