uni-app 云存储使用
章节介绍
文件存储是应用开发中常见的需求,用于存储图片、视频、音频、文档等文件。uni-app 提供了基于 uniCloud 的云存储服务,开发者可以通过云存储实现文件的上传、下载、删除、管理等操作,无需关心存储服务的搭建、配置和维护。本章节将详细介绍如何使用 uni-app 云存储,包括云存储的概念、文件上传、下载、删除、管理等操作,帮助开发者高效地管理和使用云存储服务。
核心知识点讲解
1. 云存储概述
uniCloud 云存储是一种对象存储服务,用于存储和管理文件,具有以下特点:
- 无需搭建和维护:开发者无需关心存储服务的搭建、配置、监控和维护
- 高可靠性:数据多副本存储,确保数据安全可靠
- 高并发:支持高并发文件上传和下载,应对大规模应用场景
- 弹性扩展:根据存储需求自动调整存储容量
- 易于使用:提供简洁的 API,与前端开发无缝集成
- 支持多种文件类型:支持图片、视频、音频、文档等多种文件类型
- CDN 加速:文件访问通过 CDN 加速,提高访问速度
2. 云存储的开通与配置
2.1 开通云存储服务
在使用云存储之前,需要开通 uniCloud 服务并创建服务空间:
注册并登录 DCloud 开发者账号
- 访问 DCloud 开发者中心
- 注册或登录开发者账号
开通 uniCloud 服务
- 在 DCloud 开发者中心中开通 uniCloud 服务
- 创建服务空间(选择阿里云或腾讯云)
- 记录服务空间 ID,用于后续配置
2.2 配置 HBuilderX
- 下载并安装最新版本的 HBuilderX
- 在 HBuilderX 中登录 DCloud 开发者账号
- 关联服务空间:点击 "uniCloud" > "关联服务空间或项目",选择已创建的服务空间
3. 云存储的基本操作
3.1 文件上传
文件上传是云存储的核心功能之一,用于将本地文件上传到云端。uni-app 提供了多种上传方式:
客户端直接上传:
async function uploadFile() {
try {
// 选择文件
const [chooseResult] = await uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera']
});
// 上传文件到 uniCloud
const uploadResult = await uniCloud.uploadFile({
filePath: chooseResult.tempFilePaths[0],
cloudPath: 'images/' + Date.now() + '.jpg'
});
if (uploadResult.success) {
console.log('文件上传成功:', uploadResult.fileID);
return uploadResult.fileID;
} else {
console.error('文件上传失败:', uploadResult.errMsg);
throw new Error(uploadResult.errMsg);
}
} catch (error) {
console.error('上传失败:', error);
throw error;
}
}
// 调用函数
uploadFile();上传进度监听:
async function uploadFileWithProgress() {
try {
// 选择文件
const [chooseResult] = await uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera']
});
// 上传文件到 uniCloud
const uploadResult = await uniCloud.uploadFile({
filePath: chooseResult.tempFilePaths[0],
cloudPath: 'images/' + Date.now() + '.jpg',
onProgressUpdate: (progress) => {
console.log('上传进度:', progress.progress);
console.log('已上传字节数:', progress.totalBytesSent);
console.log('总字节数:', progress.totalBytesExpectedToSend);
// 可以在这里更新 UI 显示上传进度
}
});
if (uploadResult.success) {
console.log('文件上传成功:', uploadResult.fileID);
return uploadResult.fileID;
} else {
console.error('文件上传失败:', uploadResult.errMsg);
throw new Error(uploadResult.errMsg);
}
} catch (error) {
console.error('上传失败:', error);
throw error;
}
}
// 调用函数
uploadFileWithProgress();批量上传:
async function uploadMultipleFiles() {
try {
// 选择多个文件
const [chooseResult] = await uni.chooseImage({
count: 3,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera']
});
// 批量上传文件
const uploadPromises = chooseResult.tempFilePaths.map((filePath, index) => {
return uniCloud.uploadFile({
filePath,
cloudPath: 'images/' + Date.now() + '_' + index + '.jpg'
});
});
const uploadResults = await Promise.all(uploadPromises);
const fileIDs = [];
for (const result of uploadResults) {
if (result.success) {
fileIDs.push(result.fileID);
console.log('文件上传成功:', result.fileID);
} else {
console.error('文件上传失败:', result.errMsg);
}
}
return fileIDs;
} catch (error) {
console.error('批量上传失败:', error);
throw error;
}
}
// 调用函数
uploadMultipleFiles();3.2 文件下载
文件下载是将云端文件下载到本地的操作:
下载文件到本地:
async function downloadFile(fileID) {
try {
// 下载文件
const downloadResult = await uniCloud.downloadFile({
fileID: fileID
});
if (downloadResult.success) {
console.log('文件下载成功:', downloadResult.tempFilePath);
return downloadResult.tempFilePath;
} else {
console.error('文件下载失败:', downloadResult.errMsg);
throw new Error(downloadResult.errMsg);
}
} catch (error) {
console.error('下载失败:', error);
throw error;
}
}
// 调用函数
downloadFile('cloud://service-space-id/images/1234567890.jpg');下载进度监听:
async function downloadFileWithProgress(fileID) {
try {
// 下载文件
const downloadResult = await uniCloud.downloadFile({
fileID: fileID,
onProgressUpdate: (progress) => {
console.log('下载进度:', progress.progress);
console.log('已下载字节数:', progress.totalBytesWritten);
console.log('总字节数:', progress.totalBytesExpectedToWrite);
// 可以在这里更新 UI 显示下载进度
}
});
if (downloadResult.success) {
console.log('文件下载成功:', downloadResult.tempFilePath);
return downloadResult.tempFilePath;
} else {
console.error('文件下载失败:', downloadResult.errMsg);
throw new Error(downloadResult.errMsg);
}
} catch (error) {
console.error('下载失败:', error);
throw error;
}
}
// 调用函数
downloadFileWithProgress('cloud://service-space-id/images/1234567890.jpg');3.3 文件删除
文件删除是将云端文件删除的操作:
删除单个文件:
async function deleteFile(fileID) {
try {
// 删除文件
const deleteResult = await uniCloud.deleteFile({
fileList: [fileID]
});
if (deleteResult.success) {
console.log('文件删除成功:', deleteResult.fileList);
return deleteResult.fileList;
} else {
console.error('文件删除失败:', deleteResult.errMsg);
throw new Error(deleteResult.errMsg);
}
} catch (error) {
console.error('删除失败:', error);
throw error;
}
}
// 调用函数
deleteFile('cloud://service-space-id/images/1234567890.jpg');批量删除文件:
async function deleteMultipleFiles(fileIDs) {
try {
// 批量删除文件
const deleteResult = await uniCloud.deleteFile({
fileList: fileIDs
});
if (deleteResult.success) {
console.log('文件删除成功:', deleteResult.fileList);
return deleteResult.fileList;
} else {
console.error('文件删除失败:', deleteResult.errMsg);
throw new Error(deleteResult.errMsg);
}
} catch (error) {
console.error('批量删除失败:', error);
throw error;
}
}
// 调用函数
deleteMultipleFiles([
'cloud://service-space-id/images/1234567890.jpg',
'cloud://service-space-id/images/1234567891.jpg',
'cloud://service-space-id/images/1234567892.jpg'
]);3.4 文件访问
上传到云存储的文件可以通过 URL 直接访问:
获取文件访问 URL:
function getFileURL(fileID) {
// 直接使用 fileID 作为文件访问 URL
return fileID;
}
// 调用函数
const fileURL = getFileURL('cloud://service-space-id/images/1234567890.jpg');
console.log('文件访问 URL:', fileURL);在 HTML 中使用文件 URL:
<!-- 显示图片 -->
<img src="cloud://service-space-id/images/1234567890.jpg" alt="图片" />
<!-- 播放视频 -->
<video src="cloud://service-space-id/videos/1234567890.mp4" controls></video>
<!-- 播放音频 -->
<audio src="cloud://service-space-id/audios/1234567890.mp3" controls></audio>
<!-- 下载文档 -->
<a href="cloud://service-space-id/docs/1234567890.pdf" download>下载文档</a>3. 云存储的高级操作
3.1 文件元数据管理
文件元数据是指文件的属性信息,如文件名、大小、类型、上传时间等。uniCloud 云存储支持获取和管理文件元数据:
获取文件元数据:
async function getFileMetadata(fileID) {
try {
// 获取文件元数据
const metadataResult = await uniCloud.getFileInfo({
fileList: [fileID]
});
if (metadataResult.success) {
console.log('文件元数据:', metadataResult.fileList);
return metadataResult.fileList[0];
} else {
console.error('获取文件元数据失败:', metadataResult.errMsg);
throw new Error(metadataResult.errMsg);
}
} catch (error) {
console.error('获取文件元数据失败:', error);
throw error;
}
}
// 调用函数
getFileMetadata('cloud://service-space-id/images/1234567890.jpg');3.2 文件权限管理
uniCloud 云存储支持设置文件的访问权限,确保文件安全:
文件权限类型:
- public:公开访问,任何人都可以通过 URL 访问文件
- private:私有访问,只有通过签名 URL 或云函数才能访问文件
设置文件权限:
文件权限的设置通常在云函数中进行,通过 uniCloud 的文件管理 API:
'use strict';
const cloud = uniCloud;
exports.main = async (event, context) => {
const { fileID, permission } = event;
try {
// 设置文件权限
const result = await cloud.updateFile({
fileID: fileID,
permissions: permission // 'public' 或 'private'
});
return {
code: 0,
message: '设置文件权限成功',
data: result
};
} catch (error) {
console.error('设置文件权限失败:', error);
return {
code: 500,
message: '设置文件权限失败',
error: error.message
};
}
};3.3 文件签名 URL
对于私有文件,可以通过生成签名 URL 来授权访问:
生成签名 URL:
签名 URL 的生成通常在云函数中进行,通过 uniCloud 的文件管理 API:
'use strict';
const cloud = uniCloud;
exports.main = async (event, context) => {
const { fileID, expires } = event;
try {
// 生成签名 URL
const result = await cloud.getTempFileURL({
fileList: [{
fileID: fileID,
maxAge: expires || 3600 // 过期时间,单位秒
}]
});
return {
code: 0,
message: '生成签名 URL 成功',
data: result.fileList[0]
};
} catch (error) {
console.error('生成签名 URL 失败:', error);
return {
code: 500,
message: '生成签名 URL 失败',
error: error.message
};
}
};4. 云存储的最佳实践
4.1 文件命名规范
合理的文件命名规范可以提高文件管理的效率:
- 使用唯一文件名:使用时间戳、随机数等生成唯一文件名,避免文件名冲突
- 使用目录结构:根据文件类型、用途等组织目录结构,如
images/、videos/、audios/、docs/ - 使用小写字母:文件名使用小写字母,避免大小写混淆
- 使用短横线分隔:文件名中的单词使用短横线分隔,如
user-avatar.jpg - 包含文件扩展名:文件名包含正确的文件扩展名,如
.jpg、.png、.mp4、.pdf
4.2 文件大小限制
uniCloud 云存储对文件大小有一定限制:
- 单个文件大小限制:通常为 50MB(具体以 uniCloud 官方文档为准)
- 上传速度限制:根据网络环境和文件大小不同,上传速度会有所差异
- 并发上传限制:同时上传的文件数量建议不超过 10 个
4.3 文件类型限制
uniCloud 云存储支持多种文件类型,但也有一些限制:
- 支持的文件类型:图片、视频、音频、文档等常见文件类型
- 不支持的文件类型:可执行文件、脚本文件等可能存在安全风险的文件类型
4.4 性能优化
上传优化:
- 文件压缩:上传图片、视频等文件时,先进行压缩,减少文件大小
- 分片上传:对于大文件,使用分片上传,提高上传成功率
- 批量上传:使用 Promise.all 进行批量上传,提高上传效率
- 上传进度:显示上传进度,提升用户体验
下载优化:
- 使用 CDN:利用云存储的 CDN 加速功能,提高文件访问速度
- 缓存策略:合理设置文件缓存策略,减少重复下载
- 按需下载:只下载必要的文件,避免过度下载
- 下载进度:显示下载进度,提升用户体验
存储优化:
- 定期清理:定期清理无用文件,减少存储成本
- 文件压缩:对大型文本文件进行压缩存储
- 合理使用存储:根据文件重要性选择合适的存储策略
4.5 安全最佳实践
- 文件权限:对于敏感文件,设置为私有访问权限
- 签名 URL:使用签名 URL 控制私有文件的访问权限和过期时间
- 文件验证:上传文件时验证文件类型和大小,防止恶意文件上传
- 访问控制:通过云函数控制文件的上传、下载和删除权限
- 日志记录:记录文件操作日志,便于审计和排查问题
实用案例分析
案例一:开发一个用户头像上传功能
需求分析
开发一个用户头像上传功能,包括选择图片、上传到云存储、获取头像 URL、更新用户头像等功能。
实现步骤
- 实现头像选择和上传
客户端代码:
async function uploadAvatar() {
try {
// 选择图片
const [chooseResult] = await uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera']
});
// 上传文件到 uniCloud
const uploadResult = await uniCloud.uploadFile({
filePath: chooseResult.tempFilePaths[0],
cloudPath: 'avatars/' + Date.now() + '.jpg',
onProgressUpdate: (progress) => {
console.log('上传进度:', progress.progress);
// 可以在这里更新 UI 显示上传进度
}
});
if (uploadResult.success) {
console.log('头像上传成功:', uploadResult.fileID);
return uploadResult.fileID;
} else {
console.error('头像上传失败:', uploadResult.errMsg);
throw new Error(uploadResult.errMsg);
}
} catch (error) {
console.error('上传失败:', error);
throw error;
}
}
// 调用函数
uploadAvatar();- 实现更新用户头像
云函数代码:
updateAvatar/index.js:
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
const { userId, avatarUrl } = event;
try {
// 更新用户头像
const res = await db.collection('users')
.doc(userId)
.update({
avatarUrl: avatarUrl,
updateTime: new Date()
});
return {
code: 0,
message: '更新头像成功',
data: {
updated: res.updated
}
};
} catch (error) {
console.error('更新头像失败:', error);
return {
code: 500,
message: '更新头像失败',
error: error.message
};
}
};客户端调用:
async function updateUserAvatar(userId, avatarUrl) {
try {
const res = await uniCloud.callFunction({
name: 'updateAvatar',
data: {
userId: userId,
avatarUrl: avatarUrl
}
});
if (res.result.code === 0) {
console.log('更新用户头像成功:', res.result.data);
return res.result.data;
} else {
console.error('更新用户头像失败:', res.result.message);
throw new Error(res.result.message);
}
} catch (error) {
console.error('调用云函数失败:', error);
throw error;
}
}
// 调用函数
async function handleAvatarUpload() {
try {
// 上传头像
const avatarUrl = await uploadAvatar();
// 更新用户头像
const updateResult = await updateUserAvatar('user-id', avatarUrl);
console.log('头像更新完成:', updateResult);
// 可以在这里更新 UI 显示新头像
} catch (error) {
console.error('头像更新失败:', error);
// 可以在这里显示错误提示
}
}
// 调用函数
handleAvatarUpload();- 实现头像显示
客户端代码:
<template>
<view class="avatar-container">
<image
class="avatar"
:src="userAvatar || defaultAvatar"
mode="aspectFill"
></image>
<button class="upload-btn" @click="handleUpload">上传头像</button>
</view>
</template>
<script>
export default {
data() {
return {
userAvatar: '',
defaultAvatar: 'https://via.placeholder.com/150'
};
},
mounted() {
this.getUserAvatar();
},
methods: {
async getUserAvatar() {
try {
// 调用云函数获取用户信息
const res = await uniCloud.callFunction({
name: 'getUserInfo',
data: {
userId: 'user-id'
}
});
if (res.result.code === 0) {
this.userAvatar = res.result.data.user.avatarUrl;
}
} catch (error) {
console.error('获取用户头像失败:', error);
}
},
async handleUpload() {
try {
// 上传头像
const avatarUrl = await this.uploadAvatar();
// 更新用户头像
await this.updateUserAvatar('user-id', avatarUrl);
// 更新本地头像
this.userAvatar = avatarUrl;
uni.showToast({
title: '头像上传成功',
icon: 'success'
});
} catch (error) {
console.error('头像上传失败:', error);
uni.showToast({
title: '头像上传失败',
icon: 'none'
});
}
},
async uploadAvatar() {
const [chooseResult] = await uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera']
});
const uploadResult = await uniCloud.uploadFile({
filePath: chooseResult.tempFilePaths[0],
cloudPath: 'avatars/' + Date.now() + '.jpg'
});
if (uploadResult.success) {
return uploadResult.fileID;
} else {
throw new Error(uploadResult.errMsg);
}
},
async updateUserAvatar(userId, avatarUrl) {
const res = await uniCloud.callFunction({
name: 'updateAvatar',
data: {
userId,
avatarUrl
}
});
if (res.result.code !== 0) {
throw new Error(res.result.message);
}
}
}
};
</script>
<style>
.avatar-container {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 50rpx;
}
.avatar {
width: 300rpx;
height: 300rpx;
border-radius: 50%;
margin-bottom: 30rpx;
}
.upload-btn {
width: 200rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background-color: #007AFF;
color: white;
border-radius: 40rpx;
font-size: 32rpx;
}
</style>案例二:开发一个图片上传和管理系统
需求分析
开发一个图片上传和管理系统,包括图片上传、获取图片列表、预览图片、删除图片等功能。
实现步骤
- 创建集合
创建以下集合:
images:存储图片信息
- 设计集合结构
images 集合结构:
{
_id: 'image-id', // 图片 ID,系统自动生成
fileID: 'cloud://service-space-id/images/1234567890.jpg', // 云存储文件 ID
url: 'cloud://service-space-id/images/1234567890.jpg', // 图片访问 URL
name: 'image.jpg', // 图片名称
size: 102400, // 图片大小(字节)
type: 'image/jpeg', // 图片类型
width: 1920, // 图片宽度
height: 1080, // 图片高度
userId: 'user-id', // 上传用户 ID
createTime: new Date() // 上传时间
}- 实现图片上传功能
客户端代码:
async function uploadImage() {
try {
// 选择图片
const [chooseResult] = await uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera']
});
const tempFile = chooseResult.tempFiles[0];
// 上传文件到 uniCloud
const uploadResult = await uniCloud.uploadFile({
filePath: tempFile.path,
cloudPath: 'images/' + Date.now() + '.jpg',
onProgressUpdate: (progress) => {
console.log('上传进度:', progress.progress);
// 可以在这里更新 UI 显示上传进度
}
});
if (uploadResult.success) {
console.log('图片上传成功:', uploadResult.fileID);
// 调用云函数记录图片信息
const recordResult = await uniCloud.callFunction({
name: 'recordImage',
data: {
fileID: uploadResult.fileID,
url: uploadResult.fileID,
name: tempFile.name,
size: tempFile.size,
type: tempFile.type,
width: tempFile.width,
height: tempFile.height,
userId: 'user-id'
}
});
if (recordResult.result.code === 0) {
console.log('图片记录成功:', recordResult.result.data);
return recordResult.result.data;
} else {
console.error('图片记录失败:', recordResult.result.message);
throw new Error(recordResult.result.message);
}
} else {
console.error('图片上传失败:', uploadResult.errMsg);
throw new Error(uploadResult.errMsg);
}
} catch (error) {
console.error('上传失败:', error);
throw error;
}
}
// 调用函数
uploadImage();recordImage/index.js:
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
const { fileID, url, name, size, type, width, height, userId } = event;
try {
// 记录图片信息
const res = await db.collection('images').add({
fileID,
url,
name,
size,
type,
width,
height,
userId,
createTime: new Date()
});
return {
code: 0,
message: '记录图片成功',
data: {
id: res.id,
fileID,
url
}
};
} catch (error) {
console.error('记录图片失败:', error);
return {
code: 500,
message: '记录图片失败',
error: error.message
};
}
};- 实现获取图片列表功能
客户端代码:
async function getImageList(params) {
try {
const res = await uniCloud.callFunction({
name: 'getImageList',
data: {
userId: 'user-id',
page: params.page || 1,
pageSize: params.pageSize || 10
}
});
if (res.result.code === 0) {
console.log('获取图片列表成功:', res.result.data);
return res.result.data;
} else {
console.error('获取图片列表失败:', res.result.message);
throw new Error(res.result.message);
}
} catch (error) {
console.error('获取图片列表失败:', error);
throw error;
}
}
// 调用函数
getImageList({
page: 1,
pageSize: 10
});getImageList/index.js:
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
const { userId, page = 1, pageSize = 10 } = event;
try {
const offset = (page - 1) * pageSize;
// 获取图片列表
const res = await db.collection('images')
.where({ userId })
.orderBy('createTime', 'desc')
.skip(offset)
.limit(pageSize)
.get();
// 获取总记录数
const countRes = await db.collection('images').where({ userId }).count();
return {
code: 0,
message: '获取图片列表成功',
data: {
images: res.data,
total: countRes.total,
page,
pageSize
}
};
} catch (error) {
console.error('获取图片列表失败:', error);
return {
code: 500,
message: '获取图片列表失败',
error: error.message
};
}
};- 实现图片预览功能
客户端代码:
function previewImage(current, urls) {
uni.previewImage({
current: current,
urls: urls,
success: (res) => {
console.log('预览图片成功:', res);
},
fail: (err) => {
console.error('预览图片失败:', err);
}
});
}
// 调用函数
previewImage(
'cloud://service-space-id/images/1234567890.jpg',
[
'cloud://service-space-id/images/1234567890.jpg',
'cloud://service-space-id/images/1234567891.jpg',
'cloud://service-space-id/images/1234567892.jpg'
]
);- 实现图片删除功能
客户端代码:
async function deleteImage(id, fileID) {
try {
const res = await uniCloud.callFunction({
name: 'deleteImage',
data: {
id: id,
fileID: fileID
}
});
if (res.result.code === 0) {
console.log('删除图片成功:', res.result.data);
return res.result.data;
} else {
console.error('删除图片失败:', res.result.message);
throw new Error(res.result.message);
}
} catch (error) {
console.error('删除图片失败:', error);
throw error;
}
}
// 调用函数
deleteImage('image-id', 'cloud://service-space-id/images/1234567890.jpg');deleteImage/index.js:
'use strict';
const db = uniCloud.database();
const cloud = uniCloud;
exports.main = async (event, context) => {
const { id, fileID } = event;
try {
// 从云存储中删除文件
await cloud.deleteFile({
fileList: [fileID]
});
// 从数据库中删除记录
await db.collection('images').doc(id).remove();
return {
code: 0,
message: '删除图片成功',
data: {
id: id,
fileID: fileID
}
};
} catch (error) {
console.error('删除图片失败:', error);
return {
code: 500,
message: '删除图片失败',
error: error.message
};
}
};- 实现图片管理页面
客户端代码:
<template>
<view class="image-management">
<view class="upload-section">
<button class="upload-btn" @click="handleUpload">上传图片</button>
</view>
<view class="image-list">
<view
v-for="image in images"
:key="image._id"
class="image-item"
>
<image
class="image"
:src="image.url"
mode="aspectFill"
@click="handlePreview(image.url)"
></image>
<view class="image-info">
<text class="image-name">{{ image.name }}</text>
<text class="image-size">{{ formatSize(image.size) }}</text>
</view>
<button
class="delete-btn"
@click="handleDelete(image._id, image.fileID)"
>
删除
</button>
</view>
</view>
<view class="pagination" v-if="total > pageSize">
<button
class="page-btn"
@click="handlePrevPage"
:disabled="page <= 1"
>
上一页
</button>
<text class="page-info">{{ page }} / {{ totalPages }}</text>
<button
class="page-btn"
@click="handleNextPage"
:disabled="page >= totalPages"
>
下一页
</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
images: [],
page: 1,
pageSize: 10,
total: 0,
loading: false
};
},
computed: {
totalPages() {
return Math.ceil(this.total / this.pageSize);
}
},
mounted() {
this.getImageList();
},
methods: {
async getImageList() {
if (this.loading) return;
this.loading = true;
try {
const res = await this.$api.getImageList({
page: this.page,
pageSize: this.pageSize
});
this.images = res.images;
this.total = res.total;
} catch (error) {
console.error('获取图片列表失败:', error);
uni.showToast({
title: '获取图片列表失败',
icon: 'none'
});
} finally {
this.loading = false;
}
},
async handleUpload() {
try {
const image = await this.$api.uploadImage();
uni.showToast({
title: '图片上传成功',
icon: 'success'
});
// 重新获取图片列表
this.getImageList();
} catch (error) {
console.error('图片上传失败:', error);
uni.showToast({
title: '图片上传失败',
icon: 'none'
});
}
},
handlePreview(currentUrl) {
const urls = this.images.map(image => image.url);
uni.previewImage({
current: currentUrl,
urls: urls
});
},
async handleDelete(id, fileID) {
uni.showModal({
title: '确认删除',
content: '确定要删除这张图片吗?',
success: async (res) => {
if (res.confirm) {
try {
await this.$api.deleteImage(id, fileID);
uni.showToast({
title: '图片删除成功',
icon: 'success'
});
// 重新获取图片列表
this.getImageList();
} catch (error) {
console.error('图片删除失败:', error);
uni.showToast({
title: '图片删除失败',
icon: 'none'
});
}
}
}
});
},
handlePrevPage() {
if (this.page > 1) {
this.page--;
this.getImageList();
}
},
handleNextPage() {
if (this.page < this.totalPages) {
this.page++;
this.getImageList();
}
},
formatSize(size) {
if (size < 1024) {
return size + ' B';
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + ' KB';
} else {
return (size / (1024 * 1024)).toFixed(2) + ' MB';
}
}
}
};
</script>
<style>
.image-management {
padding: 20rpx;
}
.upload-section {
margin-bottom: 30rpx;
}
.upload-btn {
width: 100%;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background-color: #007AFF;
color: white;
border-radius: 10rpx;
font-size: 32rpx;
}
.image-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
margin-bottom: 30rpx;
}
.image-item {
background-color: #f5f5f5;
border-radius: 10rpx;
overflow: hidden;
position: relative;
}
.image {
width: 100%;
height: 200rpx;
}
.image-info {
padding: 10rpx;
}
.image-name {
display: block;
font-size: 28rpx;
margin-bottom: 5rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.image-size {
display: block;
font-size: 24rpx;
color: #999;
}
.delete-btn {
position: absolute;
top: 10rpx;
right: 10rpx;
background-color: rgba(255, 0, 0, 0.7);
color: white;
border-radius: 15rpx;
font-size: 24rpx;
padding: 5rpx 15rpx;
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin-top: 30rpx;
}
.page-btn {
width: 120rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
background-color: #f5f5f5;
border-radius: 30rpx;
font-size: 28rpx;
margin: 0 20rpx;
}
.page-btn:disabled {
opacity: 0.5;
}
.page-info {
font-size: 28rpx;
color: #333;
}
</style>学习目标
通过本章节的学习,您应该能够:
- 了解云存储的概念和特点
- 掌握云存储的开通与配置方法
- 学会云存储的基本操作:文件上传、下载、删除
- 掌握云存储的高级操作:文件元数据管理、权限管理、签名 URL
- 了解云存储的最佳实践,如文件命名规范、大小限制、类型限制
- 掌握云存储的性能优化和安全最佳实践
- 能够开发实际的云存储应用,如用户头像上传和图片管理系统
总结与展望
云存储是 uni-app 开发中的重要组成部分,它为开发者提供了一种简单、高效的文件存储和管理方式,无需关心存储服务的搭建和维护。通过本章节的学习,您已经掌握了云存储的开通、配置、基本操作、高级操作、最佳实践、性能优化和安全管理,为您开发文件存储相关的应用奠定了基础。
在后续的学习中,我们将继续探索 uni-app 的高级特性,包括云存储与前端的结合使用、云存储的监控和调试、云存储的迁移和备份等内容,帮助您成为一名更加全面的 uni-app 开发者。
记住,云存储是一种强大的工具,但也需要合理使用。在开发过程中,要注意文件的命名规范、大小限制、类型限制,遵循最佳实践,确保文件的安全存储和高效访问。