图片操作
上传图片流程
- 调用
uni.chooseImage
选择图片,可单选也可多选(多选最多九张),成功的话会返回图片的临时路径数组 - 上传至自行开发的后端接口使用
uni.uploadFile
,上传至unCloud
的话则使用uniCloud.uploadFile
- 最佳写法是使用for循环来处理这个临时路径数组,这样无论是单选还是多选,都可以正确上传
- 上传成功后会返回图片的真实路径,这时应当存储真实路径至表中
- 上传文件至
unCloud
的话,成功后图片会存储在云存储中 - 删除图片,不仅要删除数据库表中的数据,还要删除云存储中的文件
uni.chooseImage选择图片
- 最多选择九张,超过九张,只有前九张会在图片的临时路径数组中返回
- 成功的回调对象包含
tempFilePaths
和tempFiles
两个数组属性 tempFilePaths
数组的元素,是tempFiles
数组的所有path
属性值- 从基础库 2.21.0 开始,wx.chooseImage停止维护,请使用 wx.chooseMedia 代替,uniapp中使用
uni.chooseMedia
代替
js
uni.chooseImage({
success: (res) => {
console.log(res)
for (let item of res.tempFilePaths) {
}
for (let item of res.tempFiles) {
}
}
})
uni.chooseImage({
success: (res) => {
console.log(res)
for (let item of res.tempFilePaths) {
}
for (let item of res.tempFiles) {
}
}
})
单张图片上传
js
uni.chooseImage({
success: (res) => {
const tempFilePaths = res.tempFilePaths;
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
}
})
}
})
uni.chooseImage({
success: (res) => {
const tempFilePaths = res.tempFilePaths;
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
}
})
}
})
多张图片上传使用循环
js
uni.chooseImage({
success: (res) => {
const tempFilePaths = res.tempFilePaths;
for(let i = 0; i < tempFilePaths.length; i++) {
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[i],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
}
})
}
}
})
uni.chooseImage({
success: (res) => {
const tempFilePaths = res.tempFilePaths;
for(let i = 0; i < tempFilePaths.length; i++) {
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[i],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
}
})
}
}
})
如果是app或者h5端,可以设置files实现多张图片上传
js
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
let imgs = tempFilePaths.map((value, index) => {
return {
name: index,
uri: value
})
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
files: imgs,
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
}
});
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
let imgs = tempFilePaths.map((value, index) => {
return {
name: index,
uri: value
})
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
files: imgs,
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
}
});
预览图片
js
uni.previewImage({
urls: res.tempFilePaths,
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
uni.previewImage({
urls: res.tempFilePaths,
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
unicloud云函数批量上传图片
js
upload() {
// 选择图片,默认不设置count属性的话最多9张
uni.chooseImage({
success(res) {
// 通过遍历调用uniCloud.uploadFile来批量上传
for (let i = 0; i < res.tempFilePaths.length; i++) {
uni.showLoading({
title: "上传中..."
})
let filePath = res.tempFilePaths[i]
uniCloud.uploadFile({
filePath, // 必传,要上传的文件对象
cloudPath: Date.now() + "-img", // 必传,保存在云端的文件名,这里以时间戳命名
success(res) {
let imageUrl = res.fileID //云端返回的图片地址
// 调用云函数保存图片数据
uniCloud.callFunction({
name: "addImage",
// 传给云函数的数据,可根据自身需求进行改动
data:{
imageUrl: imageUrl, // 图片路径
createTime: Date.now() // 创建时间
},
success: res => {
console.log(res)
},
fail: err => {
console.log(err)
},
complete: () => {}
})
},
fail(err) {
console.log(err)
},
complete() {
uni.hideLoading()
}
})
}
}
})
},
upload() {
// 选择图片,默认不设置count属性的话最多9张
uni.chooseImage({
success(res) {
// 通过遍历调用uniCloud.uploadFile来批量上传
for (let i = 0; i < res.tempFilePaths.length; i++) {
uni.showLoading({
title: "上传中..."
})
let filePath = res.tempFilePaths[i]
uniCloud.uploadFile({
filePath, // 必传,要上传的文件对象
cloudPath: Date.now() + "-img", // 必传,保存在云端的文件名,这里以时间戳命名
success(res) {
let imageUrl = res.fileID //云端返回的图片地址
// 调用云函数保存图片数据
uniCloud.callFunction({
name: "addImage",
// 传给云函数的数据,可根据自身需求进行改动
data:{
imageUrl: imageUrl, // 图片路径
createTime: Date.now() // 创建时间
},
success: res => {
console.log(res)
},
fail: err => {
console.log(err)
},
complete: () => {}
})
},
fail(err) {
console.log(err)
},
complete() {
uni.hideLoading()
}
})
}
}
})
},
云函数addImage
需要创建一个tableImages表
js
'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
const collection = db.collection('tableImages') // 云数据库里的表名 ,记录上传图片到云存储后返回的fileID
const res = await collection.add(event) // event为客户端上传的参数
return res
};
'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
const collection = db.collection('tableImages') // 云数据库里的表名 ,记录上传图片到云存储后返回的fileID
const res = await collection.add(event) // event为客户端上传的参数
return res
};
uncloud-h5端上传图片跨域
需要在unicloud-web控制台>跨域配置>新增域名>设置安全域名
比如我前端h5地址是http://172.16.0.152:8081/#/
则安全域名设置为172.16.0.152:8081
unicloud删除图片
思路:除了删除表中的对应数据,还得删除云存储上的图片文件
创建云函数deleteImage
js
'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
const collection = db.collection('tableImages') // 根据表名获取云数据库里的表
// 同时执行删除文件和删除表中数据的操作
const res = await Promise.all([uniCloud.deleteFile({
fileList: [
event.fileId
]
}), collection.doc(event.id).remove()])
// 返回删除文件和删除表中数据的操作结果
return {
deleteFile: res[0],
deleleData: res[1]
}
}
'use strict';
const db = uniCloud.database()
exports.main = async (event, context) => {
const collection = db.collection('tableImages') // 根据表名获取云数据库里的表
// 同时执行删除文件和删除表中数据的操作
const res = await Promise.all([uniCloud.deleteFile({
fileList: [
event.fileId
]
}), collection.doc(event.id).remove()])
// 返回删除文件和删除表中数据的操作结果
return {
deleteFile: res[0],
deleleData: res[1]
}
}
多文件上传示例
vue
<template>
<view class="page">
<view class="address-box add-box">
<text class="label label-img">多图片上传示例</text>
<view class="add-img-box">
<view class="add-img-item" v-for="(item, index) in imgList" :key="index">
<image class="add-img" @click="imgInfo(index)" :src="item.path" mode="aspectFill"></image>
<image class="add-img-del" @click="delImg(index)" src="../../static/delete.png"></image>
</view>
<view v-if="imgList.length < 9" class="add-img-item" @click="openCamera">
<image class="add-img" src="../../static/add.png"></image>
</view>
</view>
<text class="label label-img">服务器图片</text>
<view class="add-img-box">
<view class="add-img-item" v-for="(item, index) in cloudimgList" :key="index">
<image class="add-img" :src="item" mode="aspectFill"></image>
<image
class="add-img-del"
@click="delcloudImg(index)"
src="../../static/delete.png"
></image>
</view>
</view>
</view>
<view @click="submit" class="address-box submit-box">
<text class="submit-btn">上传服务器</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
imgList: [],
cloudimgList: [],
imgCount: 9 //最多支持9张上传,可以修改
}
},
onLoad(e) {},
methods: {
submit(e) {
this.submitData = null
if (this.imgList.length < 1) {
uni.showToast({
title: "请添加图片",
icon: "none"
})
return false
}
uni.showLoading({
title: "上传图片",
mask: false
})
for (let i = 0; i < this.imgList.length; i++) {
console.log("test!" + this.imgList[i].path)
this.$cloud.uploadFile({
filePath: this.imgList[i].path,
cloudPath: Date.now() + "-img", //保存在云端的文件名,这里以时间戳命名
success: res => {
//保存图片的路径
this.cloudimgList.push(res.fileID)
},
fail: err => {
console.log(err)
},
complete: () => {
//uni.hideLoading();
if (this.cloudimgList.length == this.imgList.length) {
uni.hideLoading()
uni.showToast({
title: "全部上传成功!",
icon: "none"
})
}
}
})
}
},
imgInfo(i) {
let tempList = []
this.imgList.forEach(img => {
tempList.push(img.path)
})
console.log(tempList)
//显示图片
uni.previewImage({
current: i,
loop: false,
urls: tempList,
indicator: "default"
})
},
delImg(i) {
uni.showModal({
content: "确定删除这张吗",
success: res => {
if (res.confirm) {
this.imgList.splice(i, 1)
this.imgCount++
} else if (res.cancel) {
}
}
})
},
delcloudImg(i) {
var _self = this
uni.showModal({
content: "确定删除云服务器上面这张图吗",
success: res => {
if (res.confirm) {
this.$cloud.deleteFile({
fileList: [this.cloudimgList[i]],
success(res) {},
fail(err) {
console.log(err)
},
complete(res) {
uni.showToast({
title: "删除成功!",
icon: "none"
})
_self.cloudimgList.splice(i, 1)
}
})
} else if (res.cancel) {
}
}
})
},
openCamera() {
uni.chooseImage({
sourceType: ["camera"],
count: this.imgCount,
sizeType: ["compressed"],
success: e => {
this.imgList = [...this.imgList, ...e.tempFiles]
this.imgCount = 9 - this.imgList.length
console.log("imgCount", this.imgCount)
}
})
}
}
}
</script>
<style lang="scss">
.page {
width: 750rpx;
overflow: hidden;
}
.back {
font-size: 32rpx;
font-weight: 500;
line-height: 48rpx;
color: rgba(153, 153, 153, 1);
}
.back-hover {
opacity: 0.4;
}
.submit-box {
position: fixed;
bottom: 0;
left: 0;
display: flex;
width: 750rpx;
justify-content: center;
}
.submit-btn {
margin-top: 10px;
display: inline-block;
width: 670rpx;
height: 96rpx;
line-height: 96rpx;
text-align: center;
background-color: rgba(109, 221, 203, 1);
opacity: 1;
border-radius: 32rpx;
border-width: 8rpx;
border-color: rgba(255, 255, 255, 1);
box-shadow: 0rpx 8rpx 12rpx rgba(0, 0, 0, 0.16);
border-radius: 56rpx;
font-size: 39rpx;
font-weight: bold;
color: rgba(255, 255, 255, 1);
}
.submit-btn-txt {
font-size: 39rpx;
font-weight: bold;
line-height: 47rpx;
color: rgba(255, 255, 255, 1);
opacity: 1;
}
.map-box {
width: 484rpx;
height: 256rpx;
border-width: 4rpx;
border-color: rgba(255, 255, 255, 1);
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.16);
/* border-radius: 12rpx; */
position: relative;
}
.map {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 476rpx;
height: 250rpx;
}
.map-img {
position: absolute;
top: 90rpx;
left: 156rpx;
width: 230rpx;
height: 68rpx;
background-color: rgba(51, 51, 51, 0.64);
border-width: 1rpx;
border-color: rgba(0, 0, 0, 0);
border-radius: 34px;
font-size: 28rpx;
font-weight: bold;
line-height: 66rpx;
color: rgba(255, 255, 255, 1);
text-align: center;
}
.address-box {
display: flex;
width: 670rpx;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 15rpx 40rpx;
margin-bottom: 10px;
}
.label {
font-size: 36rpx;
font-weight: bold;
line-height: 50rpx;
color: #222222;
}
.label-img {
padding-left: 40rpx;
}
.address-box-txt {
align-items: flex-start;
}
.address-txt {
width: 484rpx;
height: 90rpx;
font-size: 32rpx;
font-weight: 500;
line-height: 45rpx;
color: rgba(51, 51, 51, 1);
}
.add-box {
padding: 15rpx 0;
flex-wrap: wrap;
}
.add-img-box {
display: flex;
width: 750rpx;
//padding: 0 40rpx;
padding-left: 10rpx;
flex-direction: row;
flex-wrap: wrap;
}
.add-img-item {
/* width:210rpx;
height:210rpx; */
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
position: relative;
padding: 9rpx 0;
margin-left: 20rpx;
}
.add-img-camera {
flex: 1;
}
.add-img {
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
}
.add-img-del {
position: absolute;
width: 40rpx;
height: 40rpx;
right: 8rpx;
top: 17rpx;
//background-color: rgba(238, 0, 0, 1);
border-radius: 20rpx;
}
.address-time {
width: 484rpx;
height: 88rpx;
background-color: rgba(245, 245, 245, 1);
opacity: 1;
border-radius: 24rpx;
text-align: center;
font-size: 35rpx;
font-weight: 500;
color: rgba(51, 51, 51, 1);
}
.line {
width: 750rpx;
height: 1px;
transform: scaleY(0.3);
background-color: rgba(0, 0, 0, 0.5);
}
</style>
<template>
<view class="page">
<view class="address-box add-box">
<text class="label label-img">多图片上传示例</text>
<view class="add-img-box">
<view class="add-img-item" v-for="(item, index) in imgList" :key="index">
<image class="add-img" @click="imgInfo(index)" :src="item.path" mode="aspectFill"></image>
<image class="add-img-del" @click="delImg(index)" src="../../static/delete.png"></image>
</view>
<view v-if="imgList.length < 9" class="add-img-item" @click="openCamera">
<image class="add-img" src="../../static/add.png"></image>
</view>
</view>
<text class="label label-img">服务器图片</text>
<view class="add-img-box">
<view class="add-img-item" v-for="(item, index) in cloudimgList" :key="index">
<image class="add-img" :src="item" mode="aspectFill"></image>
<image
class="add-img-del"
@click="delcloudImg(index)"
src="../../static/delete.png"
></image>
</view>
</view>
</view>
<view @click="submit" class="address-box submit-box">
<text class="submit-btn">上传服务器</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
imgList: [],
cloudimgList: [],
imgCount: 9 //最多支持9张上传,可以修改
}
},
onLoad(e) {},
methods: {
submit(e) {
this.submitData = null
if (this.imgList.length < 1) {
uni.showToast({
title: "请添加图片",
icon: "none"
})
return false
}
uni.showLoading({
title: "上传图片",
mask: false
})
for (let i = 0; i < this.imgList.length; i++) {
console.log("test!" + this.imgList[i].path)
this.$cloud.uploadFile({
filePath: this.imgList[i].path,
cloudPath: Date.now() + "-img", //保存在云端的文件名,这里以时间戳命名
success: res => {
//保存图片的路径
this.cloudimgList.push(res.fileID)
},
fail: err => {
console.log(err)
},
complete: () => {
//uni.hideLoading();
if (this.cloudimgList.length == this.imgList.length) {
uni.hideLoading()
uni.showToast({
title: "全部上传成功!",
icon: "none"
})
}
}
})
}
},
imgInfo(i) {
let tempList = []
this.imgList.forEach(img => {
tempList.push(img.path)
})
console.log(tempList)
//显示图片
uni.previewImage({
current: i,
loop: false,
urls: tempList,
indicator: "default"
})
},
delImg(i) {
uni.showModal({
content: "确定删除这张吗",
success: res => {
if (res.confirm) {
this.imgList.splice(i, 1)
this.imgCount++
} else if (res.cancel) {
}
}
})
},
delcloudImg(i) {
var _self = this
uni.showModal({
content: "确定删除云服务器上面这张图吗",
success: res => {
if (res.confirm) {
this.$cloud.deleteFile({
fileList: [this.cloudimgList[i]],
success(res) {},
fail(err) {
console.log(err)
},
complete(res) {
uni.showToast({
title: "删除成功!",
icon: "none"
})
_self.cloudimgList.splice(i, 1)
}
})
} else if (res.cancel) {
}
}
})
},
openCamera() {
uni.chooseImage({
sourceType: ["camera"],
count: this.imgCount,
sizeType: ["compressed"],
success: e => {
this.imgList = [...this.imgList, ...e.tempFiles]
this.imgCount = 9 - this.imgList.length
console.log("imgCount", this.imgCount)
}
})
}
}
}
</script>
<style lang="scss">
.page {
width: 750rpx;
overflow: hidden;
}
.back {
font-size: 32rpx;
font-weight: 500;
line-height: 48rpx;
color: rgba(153, 153, 153, 1);
}
.back-hover {
opacity: 0.4;
}
.submit-box {
position: fixed;
bottom: 0;
left: 0;
display: flex;
width: 750rpx;
justify-content: center;
}
.submit-btn {
margin-top: 10px;
display: inline-block;
width: 670rpx;
height: 96rpx;
line-height: 96rpx;
text-align: center;
background-color: rgba(109, 221, 203, 1);
opacity: 1;
border-radius: 32rpx;
border-width: 8rpx;
border-color: rgba(255, 255, 255, 1);
box-shadow: 0rpx 8rpx 12rpx rgba(0, 0, 0, 0.16);
border-radius: 56rpx;
font-size: 39rpx;
font-weight: bold;
color: rgba(255, 255, 255, 1);
}
.submit-btn-txt {
font-size: 39rpx;
font-weight: bold;
line-height: 47rpx;
color: rgba(255, 255, 255, 1);
opacity: 1;
}
.map-box {
width: 484rpx;
height: 256rpx;
border-width: 4rpx;
border-color: rgba(255, 255, 255, 1);
box-shadow: 0rpx 0rpx 24rpx rgba(0, 0, 0, 0.16);
/* border-radius: 12rpx; */
position: relative;
}
.map {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 476rpx;
height: 250rpx;
}
.map-img {
position: absolute;
top: 90rpx;
left: 156rpx;
width: 230rpx;
height: 68rpx;
background-color: rgba(51, 51, 51, 0.64);
border-width: 1rpx;
border-color: rgba(0, 0, 0, 0);
border-radius: 34px;
font-size: 28rpx;
font-weight: bold;
line-height: 66rpx;
color: rgba(255, 255, 255, 1);
text-align: center;
}
.address-box {
display: flex;
width: 670rpx;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 15rpx 40rpx;
margin-bottom: 10px;
}
.label {
font-size: 36rpx;
font-weight: bold;
line-height: 50rpx;
color: #222222;
}
.label-img {
padding-left: 40rpx;
}
.address-box-txt {
align-items: flex-start;
}
.address-txt {
width: 484rpx;
height: 90rpx;
font-size: 32rpx;
font-weight: 500;
line-height: 45rpx;
color: rgba(51, 51, 51, 1);
}
.add-box {
padding: 15rpx 0;
flex-wrap: wrap;
}
.add-img-box {
display: flex;
width: 750rpx;
//padding: 0 40rpx;
padding-left: 10rpx;
flex-direction: row;
flex-wrap: wrap;
}
.add-img-item {
/* width:210rpx;
height:210rpx; */
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
position: relative;
padding: 9rpx 0;
margin-left: 20rpx;
}
.add-img-camera {
flex: 1;
}
.add-img {
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
}
.add-img-del {
position: absolute;
width: 40rpx;
height: 40rpx;
right: 8rpx;
top: 17rpx;
//background-color: rgba(238, 0, 0, 1);
border-radius: 20rpx;
}
.address-time {
width: 484rpx;
height: 88rpx;
background-color: rgba(245, 245, 245, 1);
opacity: 1;
border-radius: 24rpx;
text-align: center;
font-size: 35rpx;
font-weight: 500;
color: rgba(51, 51, 51, 1);
}
.line {
width: 750rpx;
height: 1px;
transform: scaleY(0.3);
background-color: rgba(0, 0, 0, 0.5);
}
</style>
下载图片至手机相册
提供线上地址
js
<template>
<div>
<img src="https://img-blog.csdnimg.cn/a5afbc54539a4bc79125c6ebf36ba480.png" @click="exportPDF" />
</div>
</template>
<script>
export default {
methods: {
exportPDF() {
const Url = "https://img-blog.csdnimg.cn/a5afbc54539a4bc79125c6ebf36ba480.png"
const a = document.createElement("a")
a.href = Url
a.download = "download"
a.click()
}
}
}
</script>
<template>
<div>
<img src="https://img-blog.csdnimg.cn/a5afbc54539a4bc79125c6ebf36ba480.png" @click="exportPDF" />
</div>
</template>
<script>
export default {
methods: {
exportPDF() {
const Url = "https://img-blog.csdnimg.cn/a5afbc54539a4bc79125c6ebf36ba480.png"
const a = document.createElement("a")
a.href = Url
a.download = "download"
a.click()
}
}
}
</script>