uniapp 上传图片的两种方法

29 篇文章 1 订阅

上传图片分别有uni.uploadFile方法和base64方法,后端用nodejs作服务。

  1. uni.uploadFile方法,前端只负责上传图片,后端接收图片后进行压缩保存。(H5,安卓能正常使用)
  2. base64方法,前端先压缩图片和转换成base64再上传,后端只接收保存。(安卓不能上传图片)

uni.uploadFile方法

  1. 前端uniapp代码
<template>
	<view>
		<view class='pages'>
		  
			<view class='father_view'> 
				<view class='son_view'> 
				  <view class="title-bg">想说就说(最多120个汉字)</view>
				  <textarea class="textarea-bg" v-model="text1" @blur="inputText"  placeholder="请输入留言" /> 
				</view> 
			</view>
			
			<!-- 图片 -->
			<view class="images_box">
				<block v-for="(item, index) in imglist" :key="index">
				  <view class='img-box'>
					<image class='img' :src='item' mode='aspectFill'></image>
					<view class='img-delete' @click='imgDelete1' :data-delindex="index">
					    <image class='img' src='../../static/delect.png' ></image>  
					</view>
				  </view>
				</block>
				<view class='img-box' @click='addPic1' v-if="imglist.length<9">
					<image class='img' src='../../static/add_image.png'></image>  
				</view>
			</view>
			
			<button @click='uploadimage'>上传图片</button>			
			<button @click='viewmemo'>查看留言</button>
		</view>		
	</view>	
</template>

<script>
	export default {
		data() {
			return {
				imglist:[],//选择图片后生成的临时地址数组
				text1:'',
				imglist00:[]
			}
		},
		
		onLoad() {	},
		
		methods: {	
			//*获取文本框内容*//
			inputText:function (e) {
				this.text1 = e.detail.value	
			},
			
			//*选择图片*//
			addPic1: async function() {
				let that = this				
				uni.chooseImage({
					count: 9,  // 最多可以选择的图片张数,默认9
					sizeType: ['compressed'], // original 原图,compressed 压缩图,默认二者都有
					sourceType: ['album', 'camera'], // album 从相册选图,camera 使用相机,默认二者都有
				    success: function (res) {						
						if (that.imglist.length === 0) {
							that.imglist = res.tempFilePaths
						} else if (that.imglist.length < 9) {
							that.imglist = that.imglist.concat(res.tempFilePaths); //concat追加到数组
						}
					}
				})
			},
			
			//*显示选择后的图片*//
			imgbox: function (e) {				
			    this.imglist = e.detail.value
			},
			
			//* 删除已经选择的图片 *//
			imgDelete1: function (e) {				
				let index = e.currentTarget.dataset.delindex; //获取要删除的图片的下标,否则删除的永远是第一张 ,对应 <view class='img-delect' @click='imgDelete1' :data-delindex="index">
				this.imglist.splice(index, 1);			  	
			},
			
			//*上传图片*//
			uploadimage: function () {
				let app = getApp()
				let that = this
				let upimg = require("./upimg.js") //引用当前目录下的自定义函数
				let text2 = that.text1
				
				if (text2 == '') {
					uni.showToast({  //显示对话框
						title: "请输入留言!",
						icon: 'none',
						duration: 1000,
					});
				} else {	
					if (that.imglist.length != 0 ) { //数组不为空的时候才执行 				
						upimg.uploadimg({ //********* 调用引入的upimg.js文件uploadimg函数 ************
							url: app.globalData.url+'/imgup', //全局变量,后端接口地址
							path: that.imglist, //选取图片的临时地址数组 
							text: that.text1,  //文本框内容  
							user: app.globalData.username, 
						});
						uni.showToast({  //显示对话框
							title: "上传中!",
							icon: 'loading',
							duration: 3000,
						});					
						setTimeout(function () { //延迟执行,目的是等待上一步的uploadimg函数执行完成赋值给全局变量后再执行下面的代码
							that.imglist = []  //清空选择的图片
							that.text1 = ''   //清空文本框的内容						
						}, 1000); //延迟时间
					 
					} else {
						uni.showToast({
						  title: "请添加图片!",
						  icon: 'none',
						  duration: 1000,
						})
					}
				}
			},
			
			viewmemo:function (e) {
				uni.navigateTo({  //跳转到指定页面
					url: "../memo/memo",
				})
			}
		},
	}
</script>

<style>
	@import "./imgup.css";
</style>

多图上传函数 upimg.js 代码


//多张图片上传
function uploadimg(data) {
  var app = getApp()
  var imgurln=[]	
  var that = this
  
  i = data.i ? data.i : 0,  //当前上传的哪张图片
  success = data.success ? data.success : 0,  //上传成功的个数
  fail = data.fail ? data.fail : 0;  //上传失败的个数
  uni.uploadFile({
		url: data.url, //从调用页面传入 -- url: 'http://127.0.0.1:3000/' 后端接口地址
		filePath: data.path[i], //从调用页面传入 --path: imgbox, 选取图片的地址数组  
		name: 'img', //文件名称可以自定义,要与后端配对使用:app.post('/',upload.single('img'),function(req,res,next)
		formData: {  //这里是上传图片时一起上传的数据
			user: data.user,
			memo: data.text   //从调用页面传入 -- text:text1 文本框内容  
		},

		success: (resp) => {
			success++;//图片上传成功,图片上传成功的变量+1
			//console.log(resp.data) //在调试窗口显示后端返回的图片名称      
			imgurln = imgurln.concat(app.globalData.url + resp.data); //以图片名称拼接成网址,并追加到数组imgurln
		},

		fail: (res) => {  //失败
			fail++;//图片上传失败,图片上传失败的变量+1
			console.log('fail:' + i + "fail:" + fail);
		},

		complete: () => { //不论成功、失败都执行		
			i++; //这个图片执行完上传后,开始上传下一张
			if (i == data.path.length) {   //当图片传完时,停止调用				
				console.log('1>'+app.globalData.url);       
				console.log('执行完毕');
				console.log('成功:' + success + " 失败:" + fail);
			} else { //若图片还没有传完,则继续调用函数
				//console.log(i);
				data.i = i;
				data.success = success;
				data.fail = fail;
				that.uploadimg(data);
			}
		}
    });
}

module.exports.uploadimg = uploadimg; //把uploadimg函数暴露,才能在其它js文件引用此函数。 

遍历数组方式上传多图更简单,不必再调用自定义多图上传函数。
在这里插入图片描述

`

  1. 后端nodejs代码
var express=require('express')
var app=express()
var router=express.Router()
var multer=require('multer')
var path=require('path')
var image = require("imageinfo")
var mssql =require("mssql")  //引用mssql
var config = require('../config.js') //引用config.js文件
var request = require("request")
	
var storage = multer.diskStorage({ 
    destination: function (req, file, cb) {
        cb(null, 'public/imgtemp/');  	// 接收到文件后的保存路径,需要手动创建  
    },
    filename: function (req, file, cb) { 
		cb(null, Date.now() + "-" + file.originalname);  // 将保存文件名设置为: 时间戳 + 文件原始名,比如 151342376785-123.jpg
	}
});
var upload = multer({ storage: storage })
var type = upload.single('img')  //与前端的name:'img'对应

//* 接收图片 *//
router.post('/',type,function(req,res,next){
	console.log('01>>',req.file);
	console.log('02>>',req.body);
	//console.log('03>>',req.file.path);
	res.send(req.file.filename); //向前端返回当前上传成功的文件名	
	
	mssql.connect(config, function (err) {  //连接数据库
	    if (err) {
			console.log('数据库连接失败')
			return callback(err);			  
		} else {
			//console.log('数据库连接成功')		    		        
			var user1 = req.body.user ;
			var memo1 = req.body.memo ;  //req.body 解析前端formdata传递过来的数据 //req.query 解析前端data传递过来的数据
			var filename1 = req.file.filename ;
			var request = new mssql.Request();
			request.query("INSERT INTO wx_bbs (username,memo,filename) VALUES ('"+ user1 +"','"+ memo1 +"','"+ filename1 +"')",function (err, recordsets,returnValue) {
				if (err) {
					console.log(err);
					return
				} else {		
					//str = JSON.stringify(recordsets.recordset); //将查询结果转换成json格式
					//res.send(str);  //响应请求,将数据发送到前端
					console.log('执行sql脚本成功');  //在调试窗口显示
				}
			})
		};
		
		mssql.end;  //结束连接数据库
	});	

	// 压缩图片并删除原图 //
	var images = require("images")
	var fs=require('fs') 
	var name = './public/imgtemp/' + req.file.filename;  	//原图像文件完整路径
	var outName = './public/imgup/' + req.file.filename;	//压缩后的图像文件完整路径
	
	images(name)				   					  //加载原图像文件
	  .size(1000)					  				  //等比缩放图像到1000像素宽
	  .draw(images("./public/png/logo.png"), 10, 10)  //在(10,10)处绘制Logo
	  .save(outName, {quality:60})  				  //保存图片到文件,图片质量为60%
	
	fs.unlink(name,function(err){  	//删除原图
		if(err){								
			console.log('删除失败');
			return;
		}							
		console.log('原图删除成功');
	})	
})

module.exports = router;  //暴露模块,其它地方才能调用此模块

base64方法

  1. 前端uniapp代码
<template>
	<view>
		<view class='pages'>		  
			<view class='father_view'> 
				<view class='son_view'> 
				  <view class="title-bg">想说就说(最多120个汉字)</view>
				  <textarea class="textarea-bg" v-model="text1" @blur="inputText"  placeholder="请输入留言" /> 
				</view> 
			</view>
			
			<!-- 图片 -->
			<view class="images_box">				
				<block v-for="(item, index) in imagearr" :key="index">
				  <view class='img-box'>
					<image class='img' :src='item' mode='aspectFill'></image>
					<view class='img-delete' @click='imgDelete1' :data-delindex="index">
					    <image class='img' src='../../static/delect.png' ></image>  
					</view>
				  </view>
				</block>
				<view class='img-box' @click='addPic1' v-if="imagearr.length<9">
					<image class='img' src='../../static/add_image.png'></image>  
				</view>
			</view>
			
			<button @click='uploadimage'>上传图片</button>			
			<button @click='viewmemo'>查看留言</button>
		</view>		
	</view>	
</template>

<script>	
	export default {		
		data() {
			return {				
				imagearr: [],
				text1:''
			}
		},	
		
		methods: {	

			// 获取文本框内容
			inputText:function (e) {				
				var app = getApp()
				app.globalData.memo = e.detail.value
				this.text1 = e.detail.value
			},
			
			// 选择图片
			addPic1: async function() {
				let that = this
				uni.chooseImage({
					count: 9,
					sizeType: ['original', 'compressed'],
					sourceType: ['album','camera'],
					success: (res) => {
						if (that.imagearr.length === 0) {
							that.imagearr = res.tempFilePaths							
						} else if (that.imagearr.length < 9) {
							that.imagearr = that.imagearr.concat(res.tempFilePaths); //concat追加到数组
						}				
					}
				});
			},
			
			// 上传图片
			uploadimage: function () {				
				let that = this				
				let text2 = that.text1				
				if (text2 == '') {
					uni.showToast({  //显示对话框
						title: "请输入留言!",
						icon: 'none',
						duration: 1000,
					});
				} else {	
					if (that.imagearr.length != 0 ) { //数组不为空的时候才执行						
						that.imgCompress(that.imagearr) //调用函数imgCompress				
						setTimeout(function () { //延迟执行
							that.imagearr = []  //清空选择的图片
							that.text1 = ''   //清空文本框的内容						
						}, 3000); //延迟时间
						
						uni.showToast({  //显示对话框
							title: "上传中!",
							icon: 'loading',
							duration: 3000,
						});	
					 
					} else {
						uni.showToast({
						  title: "请添加图片!",
						  icon: 'none',
						  duration: 1000,
						})
					}
				}
			},

		    // 循环调用压缩图片
			imgCompress(tempFilePaths) {
				let compressImgs = [];
				let results = [];
				tempFilePaths.forEach((item, index) => {
					compressImgs.push(new Promise((resolve, reject) => {
						// #ifndef H5
						uni.compressImage({
							src: item,
							quality: this.quality,
							success: res => {
								//console.log('compressImage', res.tempFilePath)
								results.push(res.tempFilePath);
								resolve(res.tempFilePath);
							},
							fail: (err) => {
								//console.log(err.errMsg);
								reject(err);
							},
							complete: () => {
								//uni.hideLoading();
							}
						})
						// #endif
						// #ifdef H5				
						//调用压缩图片函数 canvasDataURL
						this.canvasDataURL(item, {  
							quality: this.quality / 100
						}, (base64Codes) => {
							//this.imgUpload(base64Codes);
							results.push(base64Codes);
							resolve(base64Codes);
						})
						// #endif
					}))
				})
				Promise.all(compressImgs) //执行所有需请求的接口
				.then((results) => {
					//uni.hideLoading();
					//this.imgUpload(results);
				})
				.catch((res, object) => {
					//uni.hideLoading();
				});
			},
			
			//压缩图片
			canvasDataURL(path, obj, callback) {				
				var img = new Image();
				img.src = path;
				img.onload = function() {
					var that = this;
					// 默认按比例压缩
					var w = that.width,
						h = that.height,
						scale = w / h;
					w = obj.width || w;
					h = obj.height || (w / scale);
					
					var quality = 0.3; // 图片质量 quality值越小,所绘制出的图像越模糊
					//生成canvas
					var canvas = document.createElement('canvas');
					var ctx = canvas.getContext('2d');
					// 创建属性节点
					var anw = document.createAttribute("width");
					anw.nodeValue = w;
					var anh = document.createAttribute("height");
					anh.nodeValue = h;
					canvas.setAttributeNode(anw);
					canvas.setAttributeNode(anh);
					ctx.drawImage(that, 0, 0, w, h);
					
					if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
						quality = obj.quality;
					}

					var base64 = canvas.toDataURL('image/jpeg', quality);					
					callback(base64);  // 回调函数返回base64的值
					//console.log(base64);
					
					var app = getApp()
					var user = app.globalData.username;
					var url = app.globalData.url;
					var memo = app.globalData.memo;
					//向后端上传数据
					uni.request({						
						url: url+'/imgup',
						data: {        
							img64: base64 ,
							user: user ,
							memo: memo 
						},
						method: 'POST',
						header: { 'content-type': 'application/json' },
						success: (res) => {  //请求成功
						    console.log(res.data)  //在设计调试窗口显示后端返回的结果	
						},
						fail: () => {
							
						},
						complete: () => {
							
						}
					})
				}
			},
			
			// 删除已经选择的图片
			imgDelete1: function (e) {				
				let index = e.currentTarget.dataset.delindex; 
				//获取要删除的图片的下标,否则删除的永远是第一张 ,对应 <view class='img-delect' @click='imgDelete1' :data-delindex="index">
				this.imagearr.splice(index, 1);			  	
			},
			
			// 查看留言
			viewmemo:function (e) {
				uni.navigateTo({  //跳转到指定页面
					url: "../memo/memo",
				})
			}
		},
	}
</script>

<style>
	@import "./imgup.css";
</style>

  1. 后端nodejs代码
var express=require('express')
var app=express()
var router=express.Router()
var mssql =require("mssql")  //引用mssql
var config = require('../config.js') //引用config.js文件
var fs=require('fs') 

//* 接收图片 *//
router.post('/',function(req,res) {	
	var user1 = req.body.user ;
	var memo1 = req.body.memo ; 
	var imgdata = req.body.img64 ; //接收前端POST过来的base64
	var base64Data = imgdata.replace(/^data:image\/\w+;base64,/, "");  //过滤 data:image/jpeg;base64,
	var dataBuffer = new Buffer(base64Data, 'base64');
	
	var save_path = './public/imgup/'  //保存路径
	var file_name = Date.now() + '.png'  //以时间戳做文件名
	var save_name = save_path + file_name
	
	fs.writeFile(save_name, dataBuffer, function(err) {
		if(err){
		  res.send(err);
		}else{
		  res.send("后端图片保存成功!");
		  console.log("保存成功!")
		}
	});	
	
	mssql.connect(config, function (err) {  //连接数据库
	    if (err) {
			console.log('数据库连接失败')
			return callback(err);			  
		} else {
			//console.log('数据库连接成功')		
			var request = new mssql.Request();
			request.query("INSERT INTO wx_bbs (username,memo,filename) VALUES ('"+ user1 +"','"+ memo1 +"','"+ file_name +"')",function (err, recordsets,returnValue) {
				if (err) {
					console.log(err);
					return
				} else {		
					//str = JSON.stringify(recordsets.recordset); //将查询结果转换成json格式
					//res.send(str);  //响应请求,将数据发送到前端
					console.log('执行sql脚本成功');  //在调试窗口显示
				}
			})
		};
		
		mssql.end;  //结束连接数据库
	});
})

module.exports = router;  //暴露模块,其它地方才能调用此模块

注意:要在程序入口加入下图方框中的代码,不然解析不了前端POST过来的数据
在这里插入图片描述

  • 23
    点赞
  • 146
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
uniapp是一款基于Vue.js和小程序开发框架的跨平台应用开发工具,它可以帮助开发者快速构建同时在多个平台上运行的应用程序。在uniapp开发中,如果需要上传图片,可以选择使用图片压缩插件来减小图片的大小,提高上传效率。 目前,uniapp上使用的图片压缩插件主要有两种方式:基于canvas的压缩和使用第三方压缩库。 基于canvas的压缩方法是先将图片绘制到一个canvas上,然后通过调整canvas的尺寸和图片的质量来进行压缩。这种方法可以确保压缩后图片的质量,但在处理大尺寸图片时可能会占用较多的内存,导致用户体验下降。 另一种方法是使用第三方压缩库,如compressorjs和image-compressor等。这些库使用了一些压缩算法来减小图片的大小,同时保持适当的质量。使用第三方压缩库通常需要在项目中引入相应的插件,并按照插件提供的API进行调用。 具体使用图片压缩插件的步骤如下: 1. 引入图片压缩插件的相关依赖库或插件。 2. 创建一个图片上传组件,并添加上传按钮。 3. 在图片上传事件中获取用户选择的图片文件。 4. 调用图片压缩插件的API对图片进行压缩处理。 5. 将压缩后的图片上传到服务器。 值得注意的是,图片压缩并不是每个项目都必须使用的功能,需要根据具体需求和项目的实际情况来决定是否使用以及选择哪种压缩方法。另外,使用图片压缩插件时,需要考虑用户上传的图片大小和质量要求,以及对用户设备性能的影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值