代码编织梦想

由于uniapp 的 uni.uploadFile 上传的限制,无法实现上传excel、world、ppt等类型的文件,不支持下图的上传方式,故只能调用原生的方法来解决。


解决方案

1、先创建一个原生上传的组件

<template>
	<view class="lsj-file" :style="[getStyles]">
		<view ref="lsj" class="hFile" :style="[getStyles]" @click="onClick">
			<slot><view class="defview" :style="[getStyles]">上传</view></slot>
		</view>
	</view>
</template>

<script>
import {LsjFile} from './LsjFile.js' 
export default {
	name: 'Lsj-upload',
	props: {
		// 打印日志
		debug: {type: Boolean,default: false},
		// 自动上传
		instantly: {type: Boolean,default: false},
		// 上传接口参数设置
		option: {type: Object,default: ()=>{}},
		// 文件大小上限
		size: { type: Number, default: 10 },
		// 文件选择个数上限,超出后不触发点击
		count: { type: Number, default: 9 },
		// 允许上传的文件格式(多个以逗号隔开)
		formats: { type: String, default:''},
		// input file选择限制
		accept: {type: String,default: ''},
		// 微信选择文件类型 
		//all=从所有文件选择,
		//video=只能选择视频文件,
		//image=只能选择图片文件,
		//file=可以选择除了图片和视频之外的其它的文件
		wxFileType: { type: String, default: 'all' },
		// webviewID需唯一,不同窗口也不要同Id
		childId: { type: String, default: 'lsjUpload'  },
		// 文件选择触发面宽度
		width: { type: String, default: '100%' },
		// 文件选择触发面高度
		height: { type: String, default: '80rpx' },
		
		// top,left,bottom,right仅position=absolute时才需要传入
		top: { type: [String, Number], default: '' },
		left: { type: [String, Number], default: '' },
		bottom: { type: [String, Number], default: '' },
		right: { type: [String, Number], default: '' },
		// nvue不支持跟随窗口滚动
		position: { 
			type: String,
			// #ifdef APP-NVUE
			 default: 'absolute',
			// #endif
			// #ifndef APP-NVUE
			default: 'static',
			// #endif
		},
	},
	data() {
		return {
			
		}
	},
	watch: {
		option(v) {
			// #ifdef APP-PLUS
			this.lsjFile&&this.show();
			// #endif
		}
	},
	updated() {
		// #ifdef APP-PLUS
			if (this.isShow) {
				this.lsjFile&&this.show();
			}
		// #endif
	},
	computed: {
		getStyles() {
			let styles = {
				width: this.width,
				height: this.height
			}
			if (this.position == 'absolute') {
				styles['top'] = this.top
				styles['bottom'] = this.bottom
				styles['left'] = this.left
				styles['right'] = this.right
				styles['position'] = 'fixed'
			}

			return styles
		}
	},
	mounted() {
		this._size = 0;
		let WEBID = this.childId + new Date().getTime();
		this.lsjFile = new LsjFile({
			id: WEBID,
			debug: this.debug,
			width: this.width,
			height: this.height,
			option: this.option,
			instantly: this.instantly,
			// 限制条件
			prohibited: {
				// 大小
				size: this.size,
				// 允许上传的格式
				formats: this.formats,
				// 限制选择的格式
				accept: this.accept,
				count: this.count
			},
			onchange: this.onchange,
			onprogress: this.onprogress,
		});
		this.create();
		
	},
	beforeDestroy() {
		// #ifdef APP-PLUS
		this.lsjFile.dom.close();
		// #endif
	},
	methods: {
		setFiles(array) {
			if (array instanceof Map) {
				for (let [key, item] of array) {
					item['progress'] = 100;
					item['type'] = 'success';
					this.lsjFile.files.set(key,item);
				}
			}
			else if (Array.isArray(array)) {
				array.forEach(item=>{
					if (item.name) { 
						item['progress'] = 100;
						item['type'] = 'success';
						this.lsjFile.files.set(item.name,item);
					}
				});
			}
			this.onchange(this.lsjFile.files);
		},
		setData() {
			this.lsjFile&&this.lsjFile.setData(...arguments);
		},
		getDomStyles(callback) {
			// #ifndef APP-NVUE
			let view = uni
				.createSelectorQuery()
				.in(this)
				.select('.lsj-file')
			view.fields(
				{
					size: true,
					rect: true
				},
				({ height, width, top, left, right, bottom }) => {
					uni.createSelectorQuery()
					.selectViewport()
					.scrollOffset(({ scrollTop }) => {
						return callback({
							top: parseInt(top) + parseInt(scrollTop) + 'px',
							left: parseInt(left) + 'px',
							width: parseInt(width) + 'px',
							height: parseInt(height) + 'px'
						})
					})
					.exec()
				}
			).exec()
			// #endif
			// #ifdef APP-NVUE
			const dom = weex.requireModule('dom')
			dom.getComponentRect(this.$refs.lsj, ({ size: { height, width, top, left, right, bottom } }) => {
				return callback({
					top: parseInt(top) + 'px',
					left: parseInt(left) + 'px',
					width: parseInt(width) + 'px',
					height: parseInt(height) + 'px',
					right: parseInt(right) + 'px',
					bottom: parseInt(bottom) + 'px'
				})
			})
			// #endif
		},
		show() {
			this.isShow = true;
			// #ifdef APP-PLUS
			this.lsjFile&&this.getDomStyles(styles => {
				this.lsjFile.dom.setStyle(styles)
			});
			// #endif
			// #ifdef H5
			this.lsjFile.dom.style.display = 'inline'
			// #endif
		},
		hide() {
			this.isShow = false;
			// #ifdef APP-PLUS
			this.lsjFile&&this.lsjFile.dom.setStyle({
				top: '-100px',
				left:'0px',
				width: '1px',
				height: '100px',
			});
			// #endif
			// #ifdef H5
			this.lsjFile.dom.style.display = 'none'
			// #endif
		},
		/**
		 * 手动提交上传
		 * @param {string}name 文件名称,不传则上传所有type等于waiting和fail的文件
		 */
		upload(name) {
			this.lsjFile&&this.lsjFile.upload(name);
		},
		/**
		 * @returns {Map} 已选择的文件Map集
		 */
		onchange(files) {
			this.$emit('change',files);
			this._size = files.size;
			return files.size >= this.count ? this.hide() : this.show();
		},
		/**
		 * @returns {object} 当前上传中的对象
		 */
		onprogress(item,end=false) {
			this.$emit('progress',item);
			if (end) {
				setTimeout(()=>{
					this.$emit('uploadEnd',item);
				},0);
			}
		},
		/**
		 * 移除组件内缓存的某条数据
		 * @param {string}name 文件名称,不指定默认清除所有文件
		 */
		clear(name) {
			this.lsjFile.clear(name);
		},
		// 创建选择器
		create() {
			// 若iOS端服务端处理不了跨域就将hybrid目录内的html放到服务端去,并将此处path改成服务器上的地址
			let path = '/uni_modules/lsj-upload/hybrid/html/uploadFile.html';
			let dom = this.lsjFile.create(path);
			// #ifdef H5
			this.$refs.lsj.$el.appendChild(dom);
			// #endif
			// #ifndef APP-PLUS
			this.show();
			// #endif
			// #ifdef APP-PLUS
			dom.setStyle({position: this.position});
			dom.loadURL(path);
			setTimeout(()=>{
				// #ifdef APP-NVUE
				plus.webview.currentWebview().append(dom);
				// #endif
				// #ifndef APP-NVUE
				this.$root.$scope.$getAppWebview().append(dom);
				// #endif
				this.show();
			},300)
			// #endif
		},
		// 点击选择附件
		onClick() {
			if (this._size >= this.count) {
				this.toast(`只允许上传${this.count}个文件`);
				return;
			}
			
			// #ifdef MP-WEIXIN
			if (!this.isShow) {return;}
			let count = this.count - this._size;
			this.lsjFile.chooseMessageFile(this.wxFileType,count);
			// #endif
		},
		toast(msg) {
			uni.showToast({
				title: msg,
				icon: 'none'
			});
		}
	}
}
</script>

<style scoped>
.lsj-file {
	/* display: inline-block; */
}
.defview {
	/* background-color: #007aff;
	color: #fff;
	border-radius: 10rpx;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 28rpx; */
}
.hFile {
	/* position: relative;
	overflow: hidden; */
}
</style>

 LsjFile.js

export class LsjFile {
	constructor(data) {
		this.dom = null;
		// files.type = waiting;//(等待上传)|| loading(上传中)|| success(成功) || fail(失败)
		this.files = new Map();
		this.debug = data.debug || false;
		this.id = data.id;
		this.width = data.width;
		this.height = data.height;
		this.option = data.option;
		this.instantly = data.instantly;
		this.prohibited = data.prohibited;
		this.onchange = data.onchange;
		this.onprogress = data.onprogress;
		this.uploadHandle = this._uploadHandle;
		// #ifdef MP-WEIXIN
		this.uploadHandle = this._uploadHandleWX;
		// #endif
	}
	
	
	/**
	 * 创建File节点
	 * @param {string}path webview地址
	 */
	create(path) {
		if (!this.dom) {
			// #ifdef H5
				let dom = document.createElement('input');
				dom.type = 'file'
				dom.value = ''
				dom.style.height = this.height
				dom.style.width = this.width
			    // dom.style.visibility = 'hidden'
				dom.style.position = 'absolute'
				dom.style.top = 0
				dom.style.left = 0
				dom.style.right = 0
				dom.style.bottom = 0
				dom.style.opacity = 0
				dom.style.zIndex = 0
				dom.accept = this.prohibited.accept;
				if (this.prohibited.count > 1) {
				dom.multiple = 'multiple';
				}
				dom.onchange = event => {
					for (let file of event.target.files) {
						this.addFile(file);
					}
					this.dom.value = '';
				};
				this.dom = dom;
			// #endif
		
			// #ifdef APP-PLUS
				let styles = {
					top: '-100px',
					left: 0,
					width: '1px',
					height: '1px',
					background: 'transparent' 
				};
				let extras = {
					debug: this.debug,
					instantly: this.instantly,
					prohibited: this.prohibited,
				}
				this.dom = plus.webview.create(path, this.id, styles,extras);
				this.setData(this.option); 
				this._overrideUrlLoading();
			// #endif
			return this.dom;
		}
	}
	
	copyObject(obj) {
		if (typeof obj !== "undefined") {
			return JSON.parse(JSON.stringify(obj));
		} else {
			return obj;
		}
	}
	
	/**
	 * 自动根据字符串路径设置对象中的值 支持.和[]
	 * @param	{Object} dataObj 数据源
	 * @param	{String} name 支持a.b 和 a[b]
	 * @param	{String} value 值
	 * setValue(dataObj, name, value);
	 */
	setValue(dataObj, name, value) {
		// 通过正则表达式  查找路径数据
		let dataValue;
		if (typeof value === "object") {
			dataValue = this.copyObject(value);
		} else {
			dataValue = value;
		}
		let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g");
		const patten = name.match(regExp);
		// 遍历路径  逐级查找  最后一级用于直接赋值
		for (let i = 0; i < patten.length - 1; i++) {
			let keyName = patten[i];
			if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {};
			dataObj = dataObj[keyName];
		}
		// 最后一级
		dataObj[patten[patten.length - 1]] = dataValue;
		this.debug&&console.log('参数更新后',JSON.stringify(this.option));
	}
	
	/**
	 * 设置上传参数
	 * @param {object|string}name 上传参数,支持a.b 和 a[b]
	 */
	setData() {
		let [name,value = ''] = arguments;
		if (typeof name === 'object') {
			Object.assign(this.option,name);
		}
		else {
			this.setValue(this.option,name,value);
		}
		
		this.debug&&console.log(JSON.stringify(this.option));
		
		// #ifdef APP-PLUS
			this.dom.evalJS(`vm.setData('${JSON.stringify(this.option)}')`);
		// #endif
	}
	
	/**
	 * 上传
	 * @param {string}name 文件名称
	 */
	async upload(name='') {
		if (!this.option.url) {
			throw Error('未设置上传地址');
		}
		
		// #ifndef APP-PLUS
		console.log('has',this.files.has(name))
			if (name && this.files.has(name)) {
				await this.uploadHandle(this.files.get(name));
			}
			else {
				for (let item of this.files.values()) {
					if (item.type === 'waiting' || item.type === 'fail') {
						await this.uploadHandle(item);
					}
				}
			}
		// #endif
		
		// #ifdef APP-PLUS
			this.dom&&this.dom.evalJS(`vm.upload('${name}')`);
		// #endif
	}
	
	// 选择文件change
	addFile(file) {
		
		let name = file.name;
		this.debug&&console.log('文件名称',name,'大小',file.size);
		
		if (file) {
			// 限制文件格式
			let path = '';
			let suffix = name.substring(name.lastIndexOf(".")+1).toLowerCase();
			let formats = this.prohibited.formats.toLowerCase();
			if (formats&&!formats.includes(suffix)) {
				this.toast(`不支持上传${suffix.toUpperCase()}格式文件`);
				return false;
			}
			// 限制文件大小
			if (file.size > 1024 * 1024 * Math.abs(this.prohibited.size)) {
				this.toast(`附件大小请勿超过${this.prohibited.size}M`)
				return false;
			}
			// #ifndef MP-WEIXIN
			path = URL.createObjectURL(file);
			// #endif
			// #ifdef MP-WEIXIN
			path = file.path;
			// #endif
			this.files.set(file.name,{file,path,name: file.name,size: file.size,progress: 0,type: 'waiting'});
			
			// #ifndef MP-WEIXIN
			this.onchange(this.files);
			this.instantly&&this.upload();
			// #endif
			
			// #ifdef MP-WEIXIN
			return true;
			// #endif
		}
	}
	
	/**
	 * 移除文件
	 * @param {string}name 不传name默认移除所有文件,传入name移除指定name的文件
	 */
	clear(name='') {
		// #ifdef APP-PLUS
		this.dom&&this.dom.evalJS(`vm.clear('${name}')`);
		// #endif
		
		if (!name) {
			this.files.clear();
		}
		else {
			this.files.delete(name); 
		}
		return this.onchange(this.files);
	}
	
	/**
	 * 提示框
	 * @param {string}msg 轻提示内容
	 */
	toast(msg) {
		uni.showToast({
			title: msg,
			icon: 'none'
		});
	}
	
	/**
	 * 微信小程序选择文件
	 * @param {number}count 可选择文件数量
	 */
	chooseMessageFile(type,count) {
		wx.chooseMessageFile({
			count: count,
			type: type,
			success: ({ tempFiles }) => {
				for (let file of tempFiles) {
					let next = this.addFile(file);
					if (!next) {return}
				}
				this.onchange(this.files);
				this.instantly&&this.upload();
			},
			fail: () => {
				this.toast(`打开失败`);
			}
		})
	}
	
	_overrideUrlLoading() {
		this.dom.overrideUrlLoading({ mode: 'reject' }, e => {
			let {retype,item,files,end} = this._getRequest(
				e.url
			);
			let _this = this;
			switch (retype) {
				case 'updateOption':
					this.dom.evalJS(`vm.setData('${JSON.stringify(_this.option)}')`);
					break
				case 'change':
					try {
						_this.files = new Map([..._this.files,...JSON.parse(unescape(files))]);
					} catch (e) {
						return console.error('出错了,请检查代码')
					}
					_this.onchange(_this.files);
					break
				case 'progress':
					try {
						item = JSON.parse(unescape(item));
					} catch (e) {
						return console.error('出错了,请检查代码')
					}
					_this._changeFilesItem(item,end);
					break
				default:
					break
			}
		})
	}
	
	_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
	}
	
	_changeFilesItem(item,end=false) {
		this.debug&&console.log('onprogress',JSON.stringify(item));
		this.onprogress(item,end);
		this.files.set(item.name,item);
	}
	// 上传接口
	_uploadHandle(item) {
		item.type = 'loading';
		delete item.responseText;
		return new Promise((resolve,reject)=>{
			this.debug&&console.log('option',JSON.stringify(this.option));
			let {url,name,method='POST',header,formData} = this.option;
			let form = new FormData();
			for (let keys in formData) {
				form.append(keys, formData[keys])
			}
			form.append(name, item.file);
			let xmlRequest = new XMLHttpRequest();
			xmlRequest.open(method, url, true);
			for (let keys in header) {
				xmlRequest.setRequestHeader(keys, header[keys])
			}
			
			xmlRequest.upload.addEventListener(
				'progress',
				event => {
					if (event.lengthComputable) {
						let progress = Math.ceil((event.loaded * 100) / event.total)
						if (progress <= 100) {
							item.progress = progress;
							this._changeFilesItem(item);
						}
					}
				},
				false
			);
			
			xmlRequest.ontimeout = () => {
				console.error('请求超时')
				item.type = 'fail';
				this._changeFilesItem(item,true);
				return resolve(false);
			}
			
			xmlRequest.onreadystatechange = ev => {
				if (xmlRequest.readyState == 4) {
					if (xmlRequest.status == 200) {
						this.debug&&console.log('上传完成1:' + xmlRequest.responseText)
						item['responseText'] = xmlRequest.responseText;
						item.type = 'success';
						this._changeFilesItem(item,true);
						return resolve(true);
					} else if (xmlRequest.status == 0) {
						console.error('status = 0 :请检查请求头Content-Type与服务端是否匹配,服务端已正确开启跨域,并且nginx未拦截阻止请求')
					}
					console.error('--ERROR--:status = ' + xmlRequest.status)
					item.type = 'fail';
					this._changeFilesItem(item,true);
					return resolve(false);
				}
			}
			xmlRequest.send(form)
		});
	}
	
	_uploadHandleWX(item) {
		item.type = 'loading';
		delete item.responseText;
		return new Promise((resolve,reject)=>{
			this.debug&&console.log('option',JSON.stringify(this.option));
			let form = {filePath: item.file.path,...this.option };
			form['fail'] = ({ errMsg = '' }) => {
				console.error('--ERROR--:' + errMsg)
				item.type = 'fail';
				this._changeFilesItem(item,true);
				return resolve(false);
			}
			form['success'] = res => {
				if (res.statusCode == 200) {
					this.debug&&console.log('上传完成,微信端返回不一定是字符串,根据接口返回格式判断是否需要JSON.parse:' + res.data)
					item['responseText'] = res.data;
					item.type = 'success';
					this._changeFilesItem(item,true);
					return resolve(true);
				}
				item.type = 'fail';
				this._changeFilesItem(item,true);
				return resolve(false);
			}
			
			let xmlRequest = uni.uploadFile(form);
			xmlRequest.onProgressUpdate(({ progress = 0 }) => {
				if (progress <= 100) {
					item.progress = progress;
					this._changeFilesItem(item);
				}
			})
		});
	}
}

 2、使用组件

引入组件后使用

<uploadFile @getUploadSuccess="getUploadSuccess" :uploadUrl="uploadbeforeCreatedUrl" :formData="{}" formatType="png,jpg,jpeg,pdf,docx,doc,xlsx,xls,ppt,pptx">
     <image :src="addIcon" mode="scaleToFill" />
</uploadFile>

// uploadUrl为上传的路径

// 文件上传成功回调
 getUploadSuccess(fileData){
        let resdata = JSON.parse(fileData.responseText);
        this.form.activityResource.push(resdata.data);
        this.$forceUpdate();
 },

效果图

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/QQ_Empire/article/details/127994164

uni-app:web-view实现文件(非图片视频文件)上传与下载-爱代码爱编程

在APP最近开发的一个功能模块中,需要实现非图片与视频的文件上传与下载功能,查看了很多资料,也踩了不少坑。现在记录一下,希望可以帮到有需要的同学。 一:上传 首先需要创建一个web-view页面,在pages.json中配置web-view的页面路径为(/pages/exp/web_view),如下: <template> <vi

uniapp进行文件的选取和上传-爱代码爱编程

h5端的可以直接使用 <input type="file" accept="" multiple> //accept是用来规定选择文件的类型的,multiple可以用来多选 选到了文件就可以使用formdata添加文件进行上传 接下来是app端的 图片类型的自带的uni.chooseImage(OBJECT)就可以进行多选了 详情看官

uni 单选回显数据_uniapp开发h5链接(ios内使用)-爱代码爱编程

在使用uniap开发h5项目(主要是信息的提交)遇到不少问题,进行以下总结: 1.项目尽量简洁,去掉不必要的插件,js等,注意模块的懒加载: 本次是项目是将h5链接放入ios的app中进行调用 跨域问题,后端配置请求头进行处理。 图片跨域,后端配置后,在js图片对象添加 image.crossOrigin = 'anonymous' 2.图片

uni-app多文件上传后端Node.js多文件接收-爱代码爱编程

uni-app 代码 选择图片代码(uniapp 代码示例) 选择图片代码以及文档 uni.chooseImage({ success: (chooseImageRes) => { const tempFilePaths = chooseImageRes.tempFilePaths; } }); 上传图片

Android文件上传返回数据,【报Bug】uni.uploadFile上传文件,安卓APP没有返回值,需返回上一页面,控制台才会打印出来(H5正常)...-爱代码爱编程

详细问题描述 (DCloud产品不会有明显的bug,所以你遇到的问题大都是在特定环境下才能重现的问题,请仔细描述你的环境和重现方式,否则DCloud很难排查解决你的问题) [内容] 重现步骤 用uni.uploadFile上传文件,在安卓APP上面没有任何返回值,success fail complete 都没有执行,当返回上一页面时,控制台才

uniapp阿里云STS上传文件-爱代码爱编程

文章目录 uniapp阿里云STS上传文件需求问题所在1. 我们使用uniapp作为APP开发工具,阿里云OSS提供的一些SDK不兼2. 后端需要单独开发一个给前端调用OSS接口获取token的接口可能遇到的问题1. OSS老是提示跨域2. uniapp的代码问题代码部分1. 需要引用的依赖``npm install js-base64````np

uniapp 开发uploader文件上传组件-爱代码爱编程

最近本人在开发时uniapp小程序需要使用uploader组件,但是老是遇到一些奇怪的坑,于是就写了个原生分享一下 uploader组件是我们经常用到的来看下如何使用吧: 一、准备一张带上传符号的图片 二、给图片所有写点样式 <view class="uploader-warpper"> <image

uniapp实现h5录音功能-爱代码爱编程

uniapp实现h5录音功能 uniapp录音功能是不支持h5的,很多小伙伴可能会遇到在h5实现不了录音功能。下面我将为大家介绍一种我亲测的在uniapp实现h5中的录音。 recorder-core的使用方式: 1、先通过npm安装,然后通过import/require引入 //通过npm安装 npm install recorder-

uniapp如何上传文件file格式到服务器-爱代码爱编程

前言:使用uniapp开发混合app时碰到后台需要发送multipart/form-data请求(传文件file对象),但uni.request发送form-data请求无效(uni.request无法发送文件file对象),而且uniapp不支持 new FormData,会报错:TypeError: Cannot read property 'inde

uniapp文件上传(任意文件,多文件上传)-爱代码爱编程

此处代码只针对APP,如果要针对全端们可以参考这个。https://ext.dcloud.net.cn/plugin?id=5459 同样项目需求是这样要求可以在APP上传任意文件,没法啊,硬着头皮搞啊,插件市场找啊,哎~~没一个满足需求的。根据上个链接的启发.自己写一个,当然咱们项目是APP,所以只满足了APP端。 重点 讲一下几个重点把。

h5/web 获取实时视频并预览上传-爱代码爱编程

注意:需要在 https 或者 localhost 下才能成功调起摄像头(如果是html使用file协议也能成功) 2022.01.14更新 在chrome内核的浏览器大部分能实现录制上传功能,不支持iPhone 的 safari 浏览器,兼容性较差(MediaRecorder录制api ,这个api在uc浏览器和iphone的safari浏览器中不支

uniapp 开发笔记-爱代码爱编程

1、pages.json pages 配置说明 2、字体小于12px设置,下方示例为10px字体 { font-size: 20px; transform: scale(0.5); //缩放 } 3、uniapp 强制修改原生组件的样式 /deep/ .u-tabs__wrapper__nav{ justify-conten

uniapp开发移动端上传指南-爱代码爱编程

介绍         Uniapp是 DCloud公司于2012年开始研发的能够一次代码开发,生成H5、小程序(微信、支付宝、百度、华为等)、APP等应用的技术的统称,开发工具是HBuilderX,功能非常强大,由此引申出许多技术社区与生态环境。 引言         Uniapp开发移动端上传,需要前端、后台接口的配合,是比较常见和通用的需求场景,

uniapp上传图片失败原因_-wack-的博客-爱代码爱编程

在uniapp中将临时图片地址上传获取永久地址, 刚开始是使用post方法直接调接口上传图片,一直上传失败, 后发现需使用uni.uploadFile()才能上传文件,代码如下 uni.uploadFile({ url: 'https://www.example.com/upload', // 此为上传图片的地址 file

uni-app h5 上传图片_丶清杉的博客-爱代码爱编程

uni-app H5 上传图片 uni-app H5 上传图片环境前端代码预览PDF / 图片后端接口部分代码 Java 请注意:前端代码基本来自 官网,以及我个人的使用记录,价值不大,欢迎参考,感谢指正

uniapp h5拍照上传照片_peuy的博客-爱代码爱编程

 前段时间公司要弄一个uniapp的H5拍照上传的功能,看这位博主 常德_威少 的博客完成了(博客地址:使用canvas压缩图片大小_常德_威少的博客-CSDN博客_canvas压缩图片),于是想把我写的和补充记录一下 首先调用uni.chooseImage(具体看官网),因为手机拍照像素尺寸很大,官方图片压缩不支持H5,于是参考了 常德_威少 的博客。

uni-app 上传图片 h5 微信小程序 app 均可使用_前端 小吕的博客-爱代码爱编程

文章目录 uni 上传文件使用功能函数 uni 上传文件 在uni-app中 使用 uni.request() 是无法发送文件的 因为 request data参数无法接受Fromdata格式数据 那么

微信小程序开发-爱代码爱编程

uniapp介绍 什么是uniapp uniapp是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应