uniapp实现自定义上传图片

news2024/12/24 20:25:47

目录

  • 1、布局样式
  • 2、使用uniappAPI(uni.chooseImage)
  • 3、解决bug和添加功能
    • 3.1 bug1
    • 3.2 bug2
    • 3.3 bug3
    • 3.4 点击图片进行预览
    • 3.5 删除图片
  • 4、云函数上传到云存储

1、布局样式

在正式自定义上传前我们先将静态页面搭建好。

在这里插入图片描述

样式代码:

<template>
	<view>
		<view class="content">
			<view class="images" v-for="(item,index) in 5" :key="index">
				<image class="img" src="../../static/logo.png" mode="aspectFill"></image>
				<view class="remove">x</view>
			</view>
			<view class="files" @click="addFiles">
				<view class="add">+</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				title: 'Hello'
			}
		},
		onLoad() {

		},
		methods: {
			
		}
	}
</script>

<style lang="scss" scoped>
	.content {
		padding: 30rpx;
		display: flex;
		flex-wrap: wrap;

		.files {
			width: 200rpx;
			height: 200rpx;
			background-color: #f7f7f7;
			color: #6d6d6d;
			font-size: 100rpx;
			font-weight: 100;
			display: flex;
			justify-content: center;
			align-items: center;
			margin: 10rpx;
		}

		.images {
			width: 200rpx;
			height: 200rpx;
			margin: 10rpx;
			position: relative;

			.img {
				width: 100%;
				height: 100%;
			}

			.remove {
				width: 50rpx;
				height: 50rpx;
				background-color: #f7f7f7;
				position: absolute;
				top: -5rpx;
				right: -10rpx;
				text-align: center;
				opacity: .5;
				border-radius: 0 0 0 50rpx;
				color: #c5c5c5;
			}
		}
	}
</style>

2、使用uniappAPI(uni.chooseImage)

通过uniapp的uni.chooseImage从本地相册选择图片或使用相机拍照。
在data中定义一个响应式数据来接收我们选择的图片,然后通过v-for渲染到我们的页面,达到缩略图的效果。

代码:

<template>
	<view>
		<view class="content">
			<view class="images" v-for="(item,index) in tempFiles" :key="index">
				<image class="img" :src="item.path" mode="aspectFill"></image>
				<view class="remove">x</view>
			</view>
			<view class="files" @click="addFiles">
				<view class="add">+</view>
			</view>
		</view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				tempFiles:[]
			}
		},
		onLoad() {

		},
		methods: {
			addFiles() {
				uni.chooseImage({
					count: 9, // 最大选择的张数,默认是九张,可以不写
					success:res=>{
						console.log(res);
						// 接受选择的图片数组
						this.tempFiles= res.tempFiles
					}
				})
			}
		}
	}
</script>

效果:
在这里插入图片描述

3、解决bug和添加功能

3.1 bug1

最初我们定义了只能选择九张图片,然而这个时候上图中的+(选择图片)还在,我们应该在选择了九张图片之后将它隐藏。

我们只需要加个判断即可

	<view class="files" @click="addFiles" v-if="tempFiles.length < 9">
				<view class="add">+</view>
			</view>

3.2 bug2

在我们选择了五张,在想多加几张图片时会发现之后选择的图片会将之前的图片覆盖,所有我们要将图片进行拼接。
在这里插入图片描述
在这里插入图片描述

uni.chooseImage({
	count: 9, // 最大选择的张数,默认是九张,可以不写
	success: res => {
		console.log(res);
		// 接受选择的图片数组
		this.tempFiles = [...this.tempFiles, ...res.tempFiles]
})

3.3 bug3

如果第一次选择八张,然后在选择图片,会超过原本我们只想要的九张照片,所有我们要对它进行截取。
在这里插入图片描述

			uni.chooseImage({
					count: 9, // 最大选择的张数,默认是九张,可以不写
					success: res => {
						console.log(res);
						// 接受选择的图片数组
						let oldImg = [...this.tempFiles, ...res.tempFiles]
						// console.log(oldImg);
						let newImg = oldImg.slice(0, 9)
						// console.log(newImg);
						// 在赋值前进行截取
						this.tempFiles = newImg
					}
				})

3.4 点击图片进行预览

通过uniapp的API(uni.previewImage)我们来完成预览图片这个功能。

<image @click="previewImg(index)" class="img" :src="item.path" mode="aspectFill"></image>

给每张图片添加一个点击事件,将自身的索引值传递过去。

// 预览图片
			previewImg(index) {
				// console.log(this.tempFiles);
				// 过滤
				let imgUrl = this.tempFiles.map(item => item.path)
				// console.log(imgUrl);
				uni.previewImage({
					current: index, //点击的索引值
					urls: imgUrl,
				})
			}

由于我们的数据是这样的数组对象,所以要对其进行过滤,得到一个只有地址的数组。

在这里插入图片描述

3.5 删除图片

给每个删除按钮添加点击事件,并将索引值传递过去。

<view class="remove" @click="removeImg(index)">x</view>
// 删除图片
removeImg(index) {
	this.tempFiles.splice(index, 1)
}

4、云函数上传到云存储

我们先来讲上传按钮的样式搭建一下。

<template>
	<view>
		<view class="content">
			<view class="images" v-for="(item,index) in tempFiles" :key="index">
				<image @click="previewImg(index)" class="img" :src="item.path" mode="aspectFill"></image>
				<view class="remove" @click="removeImg(index)">x</view>
			</view>
			<view class="files" @click="addFiles" v-if="tempFiles.length<9">
				<view class="add">+</view>
			</view>
		</view>
		<button class="upload" :disabled="tempFiles.length > 0 ? false : true">发表</button>
	</view>
</template>

<style lang="scss" scoped>
	.upload {
		position: absolute;
		top: -50rpx;
		right: 20rpx;
		width: 120rpx;
		height: 60rpx;
		line-height: 60rpx;
		background-color: #04c062;
		color: white;
		border-radius: 10rpx;
		text-align: center;
		font-size: 30rpx;
	}

	.content {
		padding: 30rpx;
		margin-top: 70rpx;
		display: flex;
		flex-wrap: wrap;

		.files {
			width: 200rpx;
			height: 200rpx;
			background-color: #f7f7f7;
			color: #6d6d6d;
			font-size: 100rpx;
			font-weight: 100;
			display: flex;
			justify-content: center;
			align-items: center;
			margin: 10rpx;
		}

		.images {
			width: 200rpx;
			height: 200rpx;
			margin: 10rpx;
			position: relative;

			.img {
				width: 100%;
				height: 100%;
			}

			.remove {
				width: 50rpx;
				height: 50rpx;
				background-color: #f7f7f7;
				position: absolute;
				top: -5rpx;
				right: -10rpx;
				text-align: center;
				opacity: .5;
				border-radius: 0 0 0 50rpx;
				color: #c5c5c5;
			}
		}
	}
</style>

效果:
在这里插入图片描述
客户端上传文件到云函数、云函数再上传文件到云存储,这样的过程会导致文件流量带宽耗费较大。
所以一般上传文件都是客户端直传。

添加点击事件

<button @click="uploadFn" class="upload" :disabled="tempFiles.length > 0 ? false : true">发表</button>

默认一次只能上传一个后面我们进行循环上传。

			// 上传到云存储
			uploadFn() {
				console.log(this.tempFiles);
				uniCloud.uploadFile({
					filePath: this.tempFiles[0].path,
					cloudPathAsRealPath: true, //让cloudPath作为文件存储路径
					cloudPath: "images/" + this.tempFiles[0].name //上传到images文件夹下
				}).then(res => {
					console.log(res);
				})
			}

上传成功:
在这里插入图片描述

<button @click="goUpload" class="upload" :disabled="tempFiles.length > 0 ? false : true">发表</button>
		goUpload() {
				this.tempFiles.forEach(item=>{
					this.uploadFn(item)
				})
			},
			// 上传到云存储
			uploadFn(item) {
				uniCloud.uploadFile({
					filePath: item.path,
					cloudPathAsRealPath: true, //让cloudPath作为文件存储路径
					cloudPath: "images/" + item.name //上传到images文件夹下
				}).then(res => {
					console.log(res);
				})
			}

这样就完成了上传多张图片的功能,不过我们的图片地址后面还要存储到数据库中,所以我们将其改成promise的形式,监听全部上传完后,然后存储到数据库中。

			goUpload() {
				let promissState = this.tempFiles.map(async item => {
					return await this.uploadFn(item)
				})
				// console.log(promissState);
				Promise.all(promissState).then(res => {
					// console.log(res);
					let imgUrl = res.map(item => item.fileID)
					// console.log(imgUrl);
					const objImg = {...imgUrl}
					this.uploadDataBase(objImg)
				}).catch(e => {
					console.log(e);
				})
			},
			// 上传到云存储
			uploadFn(item) {
				return uniCloud.uploadFile({
					filePath: item.path,
					// cloudPathAsRealPath: true, //让cloudPath作为文件存储路径
					// cloudPath: "images/" + item.name //上传到images文件夹下
					cloudPath: item.name,
					//文件夹模式,不允许文件覆盖
				})
			},
			// 上传到数据库
			uploadDataBase(objImg) {
				uniCloud.callFunction({
					name: 'uploadDataBase',
					data: objImg
				}).then(res => {
					console.log(res);
				})
			}

云函数

'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
	const data = await db.collection('images').add(event)
	return data
};

最终代码:

<template>
	<view>
		<view class="content">
			<view class="images" v-for="(item,index) in tempFiles" :key="index">
				<image @click="previewImg(index)" class="img" :src="item.path" mode="aspectFill"></image>
				<view class="remove" @click="removeImg(index)">x</view>
			</view>
			<view class="files" @click="addFiles" v-if="tempFiles.length<9">
				<view class="add">+</view>
			</view>
		</view>
		<button @click="goUpload" class="upload" :disabled="tempFiles.length > 0 ? false : true">发表</button>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				tempFiles: [],
			}
		},
		onLoad() {

		},
		methods: {
			addFiles() {
				uni.chooseImage({
					count: 9, // 最大选择的张数,默认是九张,可以不写
					success: res => {
						// console.log(res);
						// 接受选择的图片数组
						let oldImg = [...this.tempFiles, ...res.tempFiles]
						// console.log(oldImg);
						let newImg = oldImg.slice(0, 9)
						// console.log(newImg);
						this.tempFiles = newImg
					}
				})
			},
			// 预览图片
			previewImg(index) {
				// console.log(this.tempFiles);
				// 过滤
				let imgUrl = this.tempFiles.map(item => item.path)
				// console.log(imgUrl);
				uni.previewImage({
					current: index, //点击的索引值
					urls: imgUrl,
				})
			},
			// 删除图片
			removeImg(index) {
				this.tempFiles.splice(index, 1)
			},
			goUpload() {
				let promissState = this.tempFiles.map(async item => {
					return await this.uploadFn(item)
				})
				// console.log(promissState);
				Promise.all(promissState).then(res => {
					// console.log(res);
					let imgUrl = res.map(item => item.fileID)
					// console.log(imgUrl);
					const objImg = {...imgUrl}
					this.uploadDataBase(objImg)
				}).catch(e => {
					console.log(e);
				})
			},
			// 上传到云存储
			uploadFn(item) {
				return uniCloud.uploadFile({
					filePath: item.path,
					// cloudPathAsRealPath: true, //让cloudPath作为文件存储路径
					// cloudPath: "images/" + item.name //上传到images文件夹下
					cloudPath: item.name,
					//文件夹模式,不允许文件覆盖
				})
			},
			// 上传到数据库
			uploadDataBase(objImg) {
				uniCloud.callFunction({
					name: 'uploadDataBase',
					data: objImg
				}).then(res => {
					console.log(res);
				})
			}

		}
	}
</script>

<style lang="scss" scoped>
	.upload {
		position: absolute;
		top: -50rpx;
		right: 20rpx;
		width: 120rpx;
		height: 60rpx;
		line-height: 60rpx;
		background-color: #04c062;
		color: white;
		border-radius: 10rpx;
		text-align: center;
		font-size: 30rpx;
	}

	.content {
		padding: 30rpx;
		margin-top: 70rpx;
		display: flex;
		flex-wrap: wrap;

		.files {
			width: 200rpx;
			height: 200rpx;
			background-color: #f7f7f7;
			color: #6d6d6d;
			font-size: 100rpx;
			font-weight: 100;
			display: flex;
			justify-content: center;
			align-items: center;
			margin: 10rpx;
		}

		.images {
			width: 200rpx;
			height: 200rpx;
			margin: 10rpx;
			position: relative;

			.img {
				width: 100%;
				height: 100%;
			}

			.remove {
				width: 50rpx;
				height: 50rpx;
				background-color: #f7f7f7;
				position: absolute;
				top: -5rpx;
				right: -10rpx;
				text-align: center;
				opacity: .5;
				border-radius: 0 0 0 50rpx;
				color: #c5c5c5;
			}
		}
	}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/857420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【面试题】这道面试题真的很变态吗?

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 最近帮公司招聘&#xff0c;主要负责一面&#xff0c;所以基本上问的基础多一点。但是我在问这样一道面试题的时候&#xff0c;很少有人答对。不少人觉得…

福布斯发布2023年云计算100强榜单,OpenAI排名第一

&#x1f989; AI新闻 &#x1f680; 福布斯发布2023年云计算100强榜单&#xff0c;OpenAI排名第一 摘要&#xff1a;福布斯发布《2023年云计算100强榜单》&#xff0c;OpenAI排名第一。榜单关注全球高成长性的云计算公司&#xff0c;特别注重AI领域的发展。今年有16家新上榜…

基于自适应曲线阈值和非局部稀疏正则化的压缩感知图像复原研究【自适应曲线阈值去除加性稳态白/有色高斯噪声】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

自带flash的浏览器,免安装

一. 内容简介 自带flash的浏览器&#xff0c;免安装 二. 软件环境 2.1 FlashBrowser_v1.0.5 2.2 安装包链接 链接&#xff1a;https://pan.baidu.com/s/1O8_uHBkDMAXnj0KCfj_Urw?pwd1234 提取码&#xff1a;1234 三.主要流程 3.1 下载安装包 3.2 运行 点击CefFlashBro…

怎么裁剪视频大小尺寸?简单的裁剪方法分享

怎么裁剪视频的画面大小尺寸呢&#xff1f;有时当我们下载下来一段视频&#xff0c;由于视频的画面大小比例不同&#xff0c;会有很多的黑边&#xff0c;我们不管是观看还是进行二次编辑都非常影响体验&#xff0c;而调整视频画面比例以适应观众的设备或平台&#xff0c;比如将…

dotNet 之数据库sqlite

Sqlite3是个特别好的本地数据库&#xff0c;体积小&#xff0c;无需安装&#xff0c;是写小控制台程序最佳数据库。NET Core是同样也是.NET 未来的方向。 **硬件支持型号 点击 查看 硬件支持 详情** DTU701 产品详情 DTU702 产品详情 DTU801 产品详情 DTU802 产品详情 D…

iview 日期 datetimerange

问题&#xff1a;每次点击编辑按钮进入到编辑页面&#xff0c;活动时间明明有值&#xff0c;却还是提示请选择活动时间。 原因&#xff1a;值没绑定上 解决办法&#xff1a;v-model 修改为 :value <Form-item label"活动时间" prop"timeRange"><d…

谷粒商城第九天-对商品服务中所涉及到的表的思考

目录 一、总述 二、spu、sku、规格参数、销售属性之间的关系理解 三、相关表设计 1. 属性表 2. 基本属性分组表 3. 分组-基本属性关系表 ​4. spu基本属性值表 5. spu详情信息表 6. spu评论表 7. 商品sku值表 8. sku详情表 9. sku图片表 10. 分类表 11. 品牌表 …

什么是代码合并。PR、MR通识说明

What is it ? 首先我想先来讲讲什么是分支合并请求Merge Request(也可叫Pull Request&#xff0c;下文中全用Merge Request或其缩写MR指代)&#xff0c;以及它有什么作用&#xff08;如果你对此概念有所了解&#xff0c;你完全可以跳过What is it&#xff09;。 MR(或者PR)就…

海外应用商店优化实用指南之元数据的迭代更新

随着每天都有新应用程序加入App Store和Google Play商店&#xff0c;许多应用程序都会针对与我们相同的关键词&#xff0c;虽然我们的元数据保持不变&#xff0c;但竞争对手的应用会重新编入索引&#xff0c;最终导致我们的关键词排名随着时间的推移稳步下降。 1、迭代的重要性…

Mysql in 查询的奇怪方向

Mysql in 查询的奇怪方向 关于表字段存储的数据为 num1,num2,num3时, 还要通过多个num1,num2入参针对该字段进行查询 建表语句 CREATE TABLE test (test_ids varchar(100) DEFAULT NULL COMMENT 保存ids 以逗号分隔 ) ENGINEInnoDB;数据项 查询语句 SELECT test_ids FROM t…

OSPF工作原理及其配置命令

目录 一、OSPF&#xff08;开放式最短路径优先协议&#xff09;&#xff1a; 作用&#xff1a;防环 弊端&#xff1a; 结构化部署: 更新方式&#xff1a; 二、OSPF的数据包 三、OSPF的状态机 Down Init 2way 条件&#xff1a; Exstart Exchange Loadi…

Stephen Wolfram:让 ChatGPT 真正起作用的是什么?

What Really Lets ChatGPT Work? 让 ChatGPT 真正起作用的是什么&#xff1f; Human language—and the processes of thinking involved in generating it—have always seemed to represent a kind of pinnacle of complexity. And indeed it’s seemed somewhat remarkabl…

stm32项目(9)——基于stm32的智能门窗设计

目录 一.功能设计 二.硬件方案 1.单片机 2.显示器 3.温湿度模块 4.烟雾模块 5.光照模块 6.数字舵机 7.蓝牙模块 8. 语音识别模块 三.程序设计 四.课题意义 五.国内外发展现状 一.功能设计 本次设计的功能如下&#xff1a; 系统包括了语音模块 、传感器数据采集模块和…

冠达管理:炒股知识入门?

股市出资是指将资金投入到股票商场&#xff0c;在商场改变中获取收益的出资行为。股票商场波动性大&#xff0c;收益高&#xff0c;招引了大量出资者的眼球&#xff0c;但是也需要出资者具备一定的常识和技能。下面从多个角度剖析&#xff0c;帮助初学者了解股市出资。 一、基本…

恒运资本:股票印花税下降有什么影响?什么原因导致下降?

在进行股票教育过程中是需求收取必定的手续费的&#xff0c;比如说买卖佣钱、印花税、过户费等等。那么股票印花税下降有什么影响&#xff1f;什么原因导致下降&#xff1f;下面就由恒运资本为大家剖析&#xff1a; 股票印花税下降有什么影响&#xff1f; 1、对于企业&#xf…

Effective Java笔记(32)谨慎并用泛型和可变参数

故事的小黄花 从出生那年就飘着 童年的荡秋千 随记忆一直晃到现在 可变参数&#xff08; vararg &#xff09; 方法&#xff08;详见第 53 条&#xff09;和泛型都是在 Java 5 中就有了&#xff0c;因此你可能会期待它们可以良好地相互作用&#xff1b;遗憾的是&#xff0c;它们…

python科研应用知乎,python库如何安装

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python科研应用知乎&#xff0c;python scipy库安装&#xff0c;现在让我们一起来看看吧&#xff01; 首先cmd进入python-s目录&#xff0c;然后再输入代码 1. 安装numpy 在线安装。此方法参考网页&#xff1a; https:/…

LeaferUI - 性能强悍、简洁轻量的 HTML5 Canvas 2D 图形 UI 绘图框架,用于 web 端在线图形设计、图表、白板、数据可视化等场景

最近想做一个轻巧的在线画册和海报设计工具&#xff0c;最近发布的 LeaferUI 特别适合这样的场景。 LeaferUI 是什么&#xff1f; Leafer UI 是基于 LeaferJS 开发的一套绚丽多彩的 UI 绘图框架&#xff0c;帮助开发者快速生成图形界面。LeaferJS 是一个基于 HTML5 Canvas 开…

3个优秀的PPT模板网站,让你的演示报告更出色!

PPT&#xff0c;作为我们在日常学习和工作中常用的一种呈现工具&#xff0c;其作用和影响力不言而喻。一份精心制作的PPT不仅可以增强观众的理解和记忆&#xff0c;而且还能展示演讲者的专业性和深度。然而&#xff0c;从零开始制作PPT可能需要花费大量的时间和精力&#xff0c…