uni-app - 移动端(iOS&Android)批量上传文件,支持重传、删除、多选,携带参数,进度监控

这篇具有很好参考价值的文章主要介绍了uni-app - 移动端(iOS&Android)批量上传文件,支持重传、删除、多选,携带参数,进度监控。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

👨‍💻 作者简介:程序员半夏 , 一名全栈程序员,擅长使用各种编程语言和框架,如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个平台找到我!
🏆 本文收录于专栏: uniapp踩坑指南
🔥 专栏介绍: 本专栏提供了uni-app开发过程中必不可少的组件和解决方案。本书详细介绍了各种常用组件的使用方法和技巧,以及如何应对uniapp开发中遇到的各种问题。

全文件上传选择非原生2.0版,uniapp踩坑指南,uni-app,ios,android

前言

本文主要针对移动端(iOS和Android)。uni-app官方提供了uni.chooseFile(OBJECT)接口从本地选择选择非媒体文件。如果是图片视频的话,可以选择uni.chooseMedia(OBJECT)uni.chooseVideo(OBJECT)uni.chooseImage(OBJECT)等接口。

但是 uni.chooseFile(OBJECT)仅仅支持H5。

App H5 微信小程序 支付宝小程序 百度小程序 抖音小程序、飞书小程序 QQ小程序 快手小程序 京东小程序
x (HBuilder X2.9.9+) x(可使用wx.chooseMessageFile) x x x x x x

除了uni.chooseFile(OBJECT) 官方还提供了uni-file-picker来选择任意类型的文件上传。但是请注意该组件在移动端仍然仅支持选择图片和视频。

file-mediatype String image image/video/all 选择文件类型,all 只支持 H5 和微信小程序平台

那么移动端,想要上传文件,我们该如何操作,按照官方的说法:App端如需选择非媒体文件,可在插件市场搜索文件选择,其中Android端可以使用Native.js,无需原生插件,而iOS端需要原生插件。

这里我们选择使用插件:全文件上传选择非原生2.0版

全文件上传选择非原生2.0版,uniapp踩坑指南,uni-app,ios,android

组件原理

在生命周期mounted调用下面的代码,根据不同的平台去渲染不同的上传组件。

这段代码首先检查this.dom是否已经存在。如果不存在,根据运行环境(H5或APP-PLUS)创建一个新的input元素或webview

在H5环境下,代码直接创建一个input元素并设置其样式、属性和事件监听器。

在APP-PLUS(移动端)环境下,使用plus.webview.create()创建一个webview并设置其样式、额外属性和数据,然后再加载了一个<input :multiple="multiple" @change="onChange" :accept="accept" ref="file" class="file" type="file" />。最后,返回创建的DOM元素。

plus.webview.create()是一个用于创建Webview窗口的方法,它在uni-app的APP-PLUS环境下可用。这个方法接收四个参数:

  1. path:要加载的HTML文件的路径,通常是一个相对路径。
  2. this.id:Webview窗口的标识,用于在后续操作中引用该窗口。
  3. styles:Webview窗口的样式设置,包括位置、尺寸、背景等属性。
  4. extras:Webview窗口的额外属性,可以在窗口创建后通过plus.webview.getWebviewById()方法获取。

在这段代码中,plus.webview.create()方法用于创建一个Webview窗口,用于处理文件选择和上传。path参数指定了Webview窗口要加载的HTML文件,this.id参数为Webview窗口分配了一个唯一标识。styles参数定义了Webview窗口的样式,例如位置、尺寸和背景颜色。extras参数包含了一些额外的属性,例如debuginstantlyprohibited,这些属性可以在Webview窗口创建后通过plus.webview.getWebviewById()方法获取。

/**
 * 创建File节点
 * @param {string} path webview地址
 */
create(path) {
  if (!this.dom) {
    // #ifdef H5
    // 创建一个input元素
    let dom = document.createElement('input');
    // 设置input类型为file
    dom.type = 'file';
    // 初始化input的值为空
    dom.value = '';
    // 设置input的样式
    dom.style.height = this.height;
    dom.style.width = this.width;
    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 = 999;
    // 设置文件类型限制
    dom.accept = this.prohibited.accept;
    // 设置是否允许多选
    if (this.prohibited.multiple) {
      dom.multiple = 'multiple';
    }
    // 监听input的change事件
    dom.onchange = event => {
      // 遍历选中的文件
      for (let file of event.target.files) {
        // 如果已选文件数量超过限制,显示提示并清空input值
        if (this.files.size >= this.prohibited.count) {
          this.toast(`只允许上传${this.prohibited.count}个文件`);
          this.dom.value = '';
          break;
        }
        // 添加文件
        this.addFile(file);
      }

      // 上传文件后的操作
      this._uploadAfter();

      // 清空input值,以便下次选择
      this.dom.value = '';
    };
    // 将创建的input元素赋值给this.dom
    this.dom = dom;
    // #endif

    // #ifdef APP-PLUS
    // 设置webview的样式
    let styles = {
      top: '-200px',
      left: 0,
      width: '1px',
      height: '200px',
      background: 'transparent',
    };
    // 设置webview的额外属性
    let extras = {
      debug: this.debug,
      instantly: this.instantly,
      prohibited: this.prohibited,
    };
    // 创建webview并赋值给this.dom
    this.dom = plus.webview.create(path, this.id, styles, extras);
    // 设置webview的数据
    this.setData(this.option);
    // 重写webview的URL加载行为
    this._overrideUrlLoading();
    // #endif
    // 返回创建的DOM元素
    return this.dom;
  }
}

页面

<template>
	<view>
		<view class="uni-uploader">
			<view class="uni-uploader-head">
				<view class="uni-uploader-info">{{ files.size }}/5</view>
			</view>
			<view class="uni-uploader-body">
				<view v-for="(item,index) in files.values()" :key="index" style="margin:5px">
					<text>{{item.name.split('.')[0]}}</text>
					<text style="margin-left: 10rpx;">上传进度:{{item.progress}}%</text>
					<text @click="resetUpload(item.name)" v-if="item.type=='fail'"
						style="margin-left: 10rpx;padding: 0 10rpx;color:#fff;background-color: #007aff;">重新上传</text>
					<text @click="clear(item.name)"
						style="margin-left: 10rpx;padding: 0 10rpx;color:#fff;background-color: #e64340;">删除</text>
				</view>
				<view class="uni-uploader__input-box" v-show="files.size < 5">
					<view class="">
						<lsj-upload ref="lsjUpload" childId="upload1" width="210rpx" height="210rpx" :option="option"
							:size="size" :count="count" :debug="false" :instantly="true" @change="onChange"
							@progress="onprogress" @uploadEnd="onuploadEnd">
							<view class="uni-uploader__input">选择附件</view>
						</lsj-upload>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

全文件上传选择非原生2.0版,uniapp踩坑指南,uni-app,ios,android

设置参数

更详细的配置请参考官方文档:https://ext.dcloud.net.cn/plugin?id=5459

上传接口的参数

参数 是否必填 说明
url 上传接口地址
name 上传接口文件key,默认为file
header 上传接口请求头,header一般用来携带token
formData 上传接口额外参数

当后端接口如下面:需要接受额外的参数,此时就需要使用formData来传递需要的参数。

// 上传单个文件
	@PostMapping(value = "/UpFiles")
	public Result UpFiles(@RequestParam("id") String id ,@RequestParam("file") MultipartFile file) {
		return Result ;
	}
data() {
    return {			// 上传接口参数
        option: {
            // 上传服务器地址,需要替换为你的接口地址
            url: 'https://example/api/UpFiles',
            // 上传接口文件key,默认为file
            name: 'file',
            // 上传接口额外参数
            formData: {
                'id': id,
            },
            header:{
                "token": uni.getStorageSync("ACCESS_TOKEN")

            }

        },
    };
},

设置上传设定(文件大小,数量,多选)

data() {
    return {
        
        // 文件上传大小限制
        size: 10,
        // 文件数量限制
        count: 5,
        // 是否多选
        multiple: true,
        // 文件回显列表
        files: new Map(),
    };
},

文件选择

回调的参数,是当前所有的文件,包括之前选中的文件。我们赋值给this.files,然后强制更新视图

// 文件选择回调
onChange(files) {
    this.files = files;
    // 强制更新视图
    this.$forceUpdate();
 
},

上传状态

在页面中,我们演示了进度的监控,这个进度可以在onprogress回调中监控。

// 上传进度回调
onprogress(item) {
    // 更新当前状态变化的文件
    this.files.set(item.name, item);

    // 强制更新视图
    this.$forceUpdate();

},

上传成功/失败

上传结束回调,参数是后端接口返回的结果,此时我们可以通过['responseText']获取结果,然后加入到当前的文件中。

例如我这里将返回的结果添加到文件属性中,把文件上传到服务器后的存放地址添加到文件中。把文件存在数据库的id添加到文件中,方便后面可以删除服务器的文件。文章来源地址https://www.toymoban.com/news/detail-771105.html

// 某文件上传结束回调(成功失败都回调)
onuploadEnd(item) {

    // 更新当前窗口状态变化的文件
    this.files.set(item.name, item);
    //  上传完成后取服务端数据
    if (item['responseText']) {
        console.log('演示服务器返回的字符串JSON转Object对象');
        this.files.get(item.name).responseText = JSON.parse(item.responseText);
        this.files.get(item.name).romoteUrl =   decodeURIComponent(item.responseText.data.url);
        this.files.get(item.name).id =   decodeURIComponent(item.responseText.data.id);
    }

    // 强制更新视图
    this.$forceUpdate();

},

重传

// 指定上传某个文件
resetUpload(name) {
    this.$refs['lsjUpload'].upload(name);
},

移除文件

// 移除某个文件
clear(name) {
    console.log(name)
    // name=指定文件名,不传name默认移除所有文件
    this.$refs['lsjUpload'].clear(name);
    // 调用后端接口删除文件
    ······
},

完整代码

<template>
	<view>

		<view class="uni-uploader">
			<view class="uni-uploader-head">
				<view class="uni-uploader-info">{{ files.size }}/5</view>
			</view>
			<view class="uni-uploader-body">
				<view v-for="(item,index) in files.values()" :key="index" style="margin:5px">
					<text>{{item.name.split('.')[0]}}</text>
					<text style="margin-left: 10rpx;">上传进度:{{item.progress}}%</text>
					<text @click="resetUpload(item.name)" v-if="item.type=='fail'"
						style="margin-left: 10rpx;padding: 0 10rpx;color:#fff;background-color: #007aff;">重新上传</text>
					<text @click="clear(item.name)"
						style="margin-left: 10rpx;padding: 0 10rpx;color:#fff;background-color: #e64340;">删除</text>
				</view>
				<view class="uni-uploader__input-box" v-show="files.size < 5">
					<view class="">
						<lsj-upload ref="lsjUpload" childId="upload1" width="210rpx" height="210rpx" :option="option"
							:size="size" :count="count" :debug="false" :instantly="true" @change="onChange"
							@progress="onprogress" @uploadEnd="onuploadEnd">
							<view class="uni-uploader__input">选择附件</view>
						</lsj-upload>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				baseImageUrl: getApp().globalData.config.baseImageUrl,
				baseUrl: getApp().globalData.config.baseUrl,
				// 上传接口参数
				option: {
					 	url: 'https://example/api/UpFiles',
                        // 上传接口文件key,默认为file
                        name: 'file',
                        // 上传接口额外参数
                        formData: {
                            'id': id,
                        },
                        header:{
                            "token": uni.getStorageSync("ACCESS_TOKEN")

                        }

				},
				// 文件上传大小限制,单位是M
				size: 10,
				// 文件数量限制
				count: 5,
				// 是否多选
				multiple: true,
				// 文件回显列表
				files: new Map(),
			};
		},
		methods: {
			// 某文件上传结束回调(成功失败都回调)
			onuploadEnd(item) {
 
				this.files.set(item.name, item);

				if (item['responseText']) {
			    console.log('演示服务器返回的字符串JSON转Object对象');
        this.files.get(item.name).responseText = JSON.parse(item.responseText);
        this.files.get(item.name).romoteUrl =   decodeURIComponent(item.responseText.data.url);
        this.files.get(item.name).id =   decodeURIComponent(item.responseText.data.id);
				}

				// 强制更新视图
				this.$forceUpdate();

			},
			// 上传进度回调
			onprogress(item) {
				// 更新当前状态变化的文件
				this.files.set(item.name, item);
				// 强制更新视图
				this.$forceUpdate();

			},
			// 文件选择回调
			onChange(files) {
				this.files = files;
				// 强制更新视图
				this.$forceUpdate();
 
			},
			// 指定上传某个文件
			resetUpload(name) {
				this.$refs['lsjUpload'].upload(name);
			},
			// 移除某个文件
			clear(name) {
				console.log(name)
				// name=指定文件名,不传name默认移除所有文件
				this.$refs['lsjUpload'].clear(name);
				console.log(this.files)

			},

		}
	}
</script>

<style lang="scss">
	.feedback-body {
		background: #fff;
	}
	.uni-uploader {
		flex: 1;
		flex-direction: column;
		background-color: #fff;
	}

	.uni-uploader-head {
		display: flex;
		flex-direction: row;
		justify-content: space-between;
	}

	.uni-uploader-info {
		color: #B2B2B2;
	}

	.uni-uploader-body {
		margin-top: 16rpx;
	}

	.uni-uploader__files {
		display: flex;
		flex-direction: row;
		flex-wrap: wrap;
	}

	.uni-uploader__file {
		margin: 10rpx;
		width: 210rpx;
		height: 210rpx;
	}

	.uni-uploader__img {
		display: block;
		width: 210rpx;
		height: 210rpx;
	}

	.uni-uploader__input-box {
		position: relative;
		margin: 10rpx;
		width: 208rpx;
		height: 208rpx;
		border: 2rpx solid #D9D9D9;
	}

	.uni-uploader__input {
		position: absolute;
		z-index: 1;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		opacity: 0;
	}
</style>

到了这里,关于uni-app - 移动端(iOS&Android)批量上传文件,支持重传、删除、多选,携带参数,进度监控的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uni-app如何区分 app、h5、小程序代码; uni-app如何判断是android、ios、小程序

    uniapp是DCloud公司于2012年开始研发的能够一次代码开发,生成H5、小程序(微信、支付宝、百度、华为等)、APP等应用的技术的统称,开发工具是HBuilderX,功能非常强大,由此引申出许多技术社区与生态环境。 使用HBuilderX开发Uniapp程序的项目,用它生成多端应用,由于兼容各种

    2024年02月11日
    浏览(36)
  • uni-app之app上传pdf类型文件

    通过阅读官方文档发现, uni.chooseFile 在app端不支持非媒体文件上传; 可以使用这个插件,验证过可以上传pdf;具体使用可以去看文档 插件地址 就是还是会出现相机,这个可能需要自己解决下 实现功能:上传只能上传一个,如果文件列表有值点击上传进行toast提示,不再出现

    2024年02月13日
    浏览(37)
  • uni-app实现上传图片或者文件(直接上代码)

    在webappsRoot文件夹下创建用于接收上传文件的upload文件夹 如果是文件: 上传文件方法也可以上传图片,只需要把extension中改为图片对应为后缀名即可 controller:

    2024年02月11日
    浏览(36)
  • uni-app(android、ios) 使用蓝牙便携式打印机(热敏打印机)

    HSPOS 点密度:576点/行(8dots/mm,203dpi) 接口类型: 蓝牙(Bluetooth2.0,4.0双模,支持Android,IOS) 打印方式:图形打印(位图) 打印指令集: ESC/POS 1、 实现蓝牙连接 **B12.js方法封装 *** vue文件中内容 2、获取位图信息 vue页面中拿到像素(位图)信息; 3、开始打印; b12s.js 1、安

    2024年02月15日
    浏览(131)
  • uni-app实现上传文件至云存储的三种方式

    目录 前言 1.在uniCloud WEB控制台中可以直接上传文件 2.客户端api上传或者组件 组件上传 客户端手动api上传 3. 云函数上传文件到云存储 总结 开发者使用 uniCloud 的云存储,无需再像传统模式那样单独去购买存储空间、CDN映射、流量采购等,本篇文章主要讲解如何使用uni-app实现

    2024年02月08日
    浏览(41)
  • uni-app uni-file-picker文件上传实现拍摄从相册选择获取图片上传文档服务器(H5上传-微信小程序上传)

    前言 最近在使用uni-app写H5移动端,有一个从手机拍摄从相册选择获取图片上传到文档服务器功能。 查阅uni-app发现关于上传图片,uni-file-picker文件上传,uni.chooseImage,uni.uploadFile H5上传时它和pc端原理差不多,都是file对象上传,PC端是通过new file对象,uni-app是直接提供了 微信

    2024年02月15日
    浏览(44)
  • uni-app 支持 app端, h5端,微信小程序端 图片转换文件格式 和 base64

    uni-app 支持 app端 h5端,微信小程序端 图片转换文件格式 和 base64,下方是插件市场的地址 app端 h5端,微信小程序端 图片转换文件格式 和 base64 - DCloud 插件市场 https://ext.dcloud.net.cn/plugin?id=13926

    2024年02月13日
    浏览(36)
  • uni-app实现图片上传功能

    效果 代码  

    2024年02月13日
    浏览(43)
  • uni-app打包ios的步骤

    注意:下面的操作必须同时满足三个条件,且这三个条件都是必须得: 1.有一个苹果开发者账号(要收费) 2.有一台苹果笔记本(在笔记本上生成证书和文件) 3.有一部苹果手机(用于测试app的功能) 使用uniapp发布ios的应用的步骤如下: 点击发行——原生app——云打包 出现页面如下

    2024年02月09日
    浏览(43)
  • 【uni-app】上传图片 uni.chooseImage(),uni.uploadFile()接口使用

    图片上传在实际场景中使用广泛,例如商品图片,汽车图片等等 实现选择单张图片上传,可以删除图片。(预览功能时间原因未研究) Vue2 版本,使用uni-app框架api唤起手机相册等图片源,将图片选中到目标列表,并发送到服务器存储,存储成功得到处理后的图片名称存储到

    2024年02月05日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包