uni-app实现文件上传功能

Posted That_Jay

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app实现文件上传功能相关的知识,希望对你有一定的参考价值。

uni-app实现文件上传功能

目前找到的比较好用的一款第三方插件
文件上传插件地址 https://ext.dcloud.net.cn/plugin?id=1015
插件下载选择下载示例项目zip ,可以直接运行项目查看效果

目录结构如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200317231930880.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d1c2VqaWVnZTY=,size_16,color_FFFFFF,t_70 =200x240)

index.vue,是使用文件上传功能的当前页面

@up-success="onSuccess" 是文件上传成功以后回传的数据

<template>
	<view>
		<l-file ref="lFile" @up-success="onSuccess"></l-file>
		<view class="padding text-center">
			<view class="padding">
				<button @tap="onUpload">上传</button>
			</view>
		</view>
	</view>
</template>
<script>
	import lFile from ‘@/components/l-file/l-file.vue‘
	export default {
		components:{lFile},
		data() {
			return {
			}
		},
		methods: {
			/* 上传 */
			onUpload() { 
				this.$refs.lFile.upload({
					// #ifdef APP-PLUS
					currentWebview: this.$mp.page.$getAppWebview(),
					// #endif
					//非真实地址,记得更换
					 url: ‘https://www.example.com/upload‘,
					//默认file,上传文件的key
					name: ‘uploadFile‘,
					// header: {‘Content-Type‘:‘类型‘,‘Authorization‘:‘token‘},
					//...其他参数
				});
			},
			onSuccess(res) {
				console.log(‘上传成功回调=====33====‘,JSON.stringify(res));
				uni.showToast({
					title: JSON.stringify(res),
					icon: ‘none‘
				})
			}
		}
	}
</script>

l-file.vue,是文件上传功能的封装组件,最后加载的是index.html文件

wv.overrideUrlLoading 监听返回的文件上传结果。

getRequest(url) {  
	let theRequest = new Object(); 
	let index = url.indexOf("?");
	if (index != -1) {  
		let str = url.substring(index+1);  
		let strs = str.split("&");  
		for(let i = 0; i < strs.length; i ++) {  
			theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);  
		} 
	}  
	return theRequest;  
},
appChooseFile({currentWebview,url,name = ‘file‘,header,...formData} = {}) {
	// #ifdef APP-PLUS
	let wv = plus.webview.create("","/hybrid/html/index.html",{
		‘uni-app‘: ‘none‘, //不加载uni-app渲染层框架,避免样式冲突
		top: 0,
		height: ‘100%‘,
		background: ‘transparent‘
	},{
		url,
		header,
		key: name,
		...formData,
	});
	wv.loadURL("/hybrid/html/index.html")
	currentWebview.append(wv);
	wv.overrideUrlLoading({mode:‘reject‘},(e)=>{
		let {fileName,id} = this.getRequest(e.url);
		return this.onCommit(
		this.$emit(‘up-success‘,{fileName,data: {id,statusCode: 200}})
		);
	});
	// #endif
}

index.html 源码

<!DOCTYPE html>
<html lang="zh-cn">

	<head>
		<meta charset="UTF-8">
		<title class="title">[文件管理器]</title>
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<style type="text/css">
			.content {background: transparent;}
			.fixed {position: fixed;bottom: 0;left: 0;right: 0;width: 100%;}
			.content .mask {top: 0;background: rgba(0,0,0,.4);z-index: 90;}
			.content .file-content {z-index: 91;height: 60px;background: #fff;text-align: center;}
			.btn {position: relative;}
			.btn .file {position: absolute;z-index: 93;left: 0;right: 0;top: 0;bottom: 0;height: 60px;width: 100%;opacity: 0;}
			.btn-bg {margin-top: 10px;background: #0066CC;color: #fff;width: 80%;height: 40px;border: 0;border-radius: 5px;}
			.tis {top: 0;z-index: 95;display: none;justify-content: center;align-items: center;}
			.tis .tis-content {background: #fff;width: 60%;border-radius: 10px;padding: 20px 0;}
			.tis .tis-content img {width: 50px;height: 50px;}
			.tis-progress {margin: 10px 0;color: #999;}
			.cancel-btn {margin-top: 30px;height: 30px;line-height: 1;padding: 0 2em;background: #e3e3e3;color: #898989;border: 0;border-radius: 5px;}
		</style>
	</head>

	<body>
		
		<div class="content">
			
			<div class="fixed mask"></div>
			
			<div align="center" class="fixed tis">
				<div class="tis-content">
					<div>
						<img src="../../static/logo.png" >
					</div>
					<div class="tis-progress">
						努力上传中..
					</div>
					<div class="cancel">
						<button type="button" class="cancel-btn">取消上传</button>
					</div>
				</div>
			</div>
			
			<div class="fixed file-content">
				<div class="btn">
					<button type="button" class="btn-bg">打开文件管理器</button>
					<input class="file" type="file" />
				</div>
			</div>
		</div>
		
		<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
		<script src="js/h5-uploader.js" type="text/javascript" charset="utf-8"></script>
	</body>

</html>


h5-uploader.js 源码

负责h5代码上传文件及其进度展示,及上传结果回传

let mask = document.querySelector(".mask");
let fileDom = document.querySelector(".file");
let tis = document.querySelector(".tis");
let progress = document.querySelector(".tis-progress");
let cancel = document.querySelector(".cancel-btn");


let createUpload = (file, url, key=‘file‘, header = {},data = {}) => {
	console.log(`
	上传地址:${url}

	请求头:${JSON.stringify(header)}

	参数:${JSON.stringify(data)}
	`);
	if (!url) {return;}
	tis.style.display = ‘flex‘;
	
	let formData = new FormData();
		formData.append(key, file);
	
	for (let keys in data) {
		formData.append(keys, data[keys]);
	}
	
	let xhr = new XMLHttpRequest();
	xhr.open("POST", url, true);
	
	for (let keys in header) {
		xhr.setRequestHeader(keys, header[keys]);
	}
	xhr.upload.addEventListener("progress", function(event) {
		if(event.lengthComputable){
			let percent = Math.ceil(event.loaded * 100 / event.total) + "%";
			progress.innerText = `努力上传中..${percent}`;
		}
	}, false);
	
	xhr.ontimeout = function(){
		// xhr请求超时事件处理
		progress.innerText = ‘请求超时‘;
		setTimeout(()=>{
			tis.style.display = ‘none‘;
			plus.webview.currentWebview().close();
		},1000);
	};
	
	xhr.onreadystatechange = (ev) => {
		
		if(xhr.readyState == 4) {
			console.log(‘status:‘+xhr.status);
			
			if (xhr.status == 200) {
				progress.innerText = ‘上传成功‘;
				console.log(‘返回数据:‘+xhr.responseText);
				location.href = `callback?fileName=${file.name}&id=${xhr.responseText}`;
				
			}
			else {
				progress.innerText = ‘上传失败了‘;
			}
			
			setTimeout(()=>{
				tis.style.display = ‘none‘;
				plus.webview.currentWebview().close();
			},1000);
			
		}
	};
	xhr.send(formData);
	
	cancel.addEventListener("click", ()=>{
		xhr.abort();
		plus.webview.currentWebview().close();
	});
}


mask.addEventListener("click", () => {
	plus.webview.currentWebview().close();
});

document.addEventListener(‘UniAppJSBridgeReady‘, () => {
	let {url,key,header,formData} = plus.webview.currentWebview();
	fileDom.addEventListener(‘change‘, (event) => {
		let file = fileDom.files[0];
		if(file.size > (1024*1024 * 10)) {
			plus.nativeUI.toast(‘单个文件不能超过10M,请重新上传‘);
			return;
		}
		console.log(file.name);
		createUpload(file, url, key,header,formData);
	}, false);
});

插件地址 https://ext.dcloud.net.cn/plugin?id=1015







以上是关于uni-app实现文件上传功能的主要内容,如果未能解决你的问题,请参考以下文章

uni-app小程序实现录音功能,uniapp实现录音功能并上传java,uniapp简单实现录音功能

uni-app——小程序实现本地图片的上传以及身份证的智能识别

uni-app 微信小程序 上传图片 文件 uni.uploadFile() 、 uni.chooseImage()

uni-app图片剪切上传;uview2用使用uview1中的图片剪切上传组件,把原有代码抽取出来

uni-app文件上传

uni-app文件上传经验