引言
在移动应用开发中,文件管理是一个常见但复杂的需求,不同平台对文件系统的访问方式存在显著差异。UniApp作为跨平台开发框架,提供了一套统一的API来处理文件操作,大大简化了多平台适配工作。本文将带领大家开发一个功能完整的跨平台文件管理器,涵盖文件浏览、上传、下载、预览等核心功能。
一、项目初始化与结构设计
1. 创建UniApp项目
使用HBuilder X创建新的uni-app项目,选择默认模板:
项目结构:
├── pages
│ ├── index
│ │ ├── index.vue # 主页面
│ │ └── file-preview.vue # 文件预览页
│ └── manager
│ └── manager.vue # 文件管理页
├── static
│ ├── icons # 文件类型图标
│ └── images # 静态图片
├── uni_modules # uni模块
├── App.vue # 应用配置
└── manifest.json # 应用配置文件
2. 文件类型识别工具
创建文件类型识别工具类,用于显示不同类型的文件图标:
// utils/file-util.js
export default {
// 获取文件类型图标
getFileIcon(filename) {
const extension = filename.split('.').pop().toLowerCase();
const iconMap = {
'pdf': 'pdf-icon.png',
'doc': 'word-icon.png',
'docx': 'word-icon.png',
'xls': 'excel-icon.png',
'xlsx': 'excel-icon.png',
'jpg': 'image-icon.png',
'jpeg': 'image-icon.png',
'png': 'image-icon.png',
'mp4': 'video-icon.png',
'mp3': 'audio-icon.png',
'zip': 'archive-icon.png',
'rar': 'archive-icon.png'
};
return iconMap[extension] || 'file-icon.png';
},
// 格式化文件大小
formatFileSize(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
};
二、核心功能实现
1. 文件列表展示组件
创建可复用的文件列表组件,支持多种布局方式:
<template>
<view>
<view class="file-list">
<view
v-for="(file, index) in files"
:key="index"
class="file-item"
@click="onFileClick(file)"
>
<image
:src="getFileIcon(file.name)"
class="file-icon"
/>
<view class="file-info">
<text class="file-name">{{ file.name }}</text>
<text class="file-size">{{ formatFileSize(file.size) }}</text>
<text class="file-date">{{ formatDate(file.modifiedTime) }}</text>
</view>
<view class="file-actions">
<button @click.stop="onDownload(file)">下载</button>
<button @click.stop="onDelete(file)">删除</button>
</view>
</view>
</view>
</view>
</template>
<script>
import fileUtil from '@/utils/file-util.js';
export default {
props: {
files: {
type: Array,
default: () => []
}
},
methods: {
getFileIcon(filename) {
return fileUtil.getFileIcon(filename);
},
formatFileSize(size) {
return fileUtil.formatFileSize(size);
},
formatDate(timestamp) {
return new Date(timestamp).toLocaleDateString();
},
onFileClick(file) {
this.$emit('file-click', file);
},
onDownload(file) {
this.$emit('download', file);
},
onDelete(file) {
this.$emit('delete', file);
}
}
};
</script>
2. 文件上传功能
实现多文件选择和上传功能,支持进度显示:
<template>
<view>
<button @click="chooseFiles">选择文件</button>
<view v-for="(file, index) in uploadQueue" :key="index">
<text>{{ file.name }}</text>
<progress :percent="file.progress" show-info></progress>
</view>
</view>
</template>
<script>
export default {
data() {
return {
uploadQueue: []
};
},
methods: {
async chooseFiles() {
try {
const res = await uni.chooseFile({
count: 10,
type: 'all'
});
res.tempFiles.forEach(file => {
this.uploadFile(file);
});
} catch (error) {
uni.showToast({
title: '文件选择失败',
icon: 'none'
});
}
},
async uploadFile(file) {
const uploadTask = {
name: file.name,
size: file.size,
progress: 0
};
this.uploadQueue.push(uploadTask);
try {
const uploadRes = await uni.uploadFile({
url: 'https://your-api-domain.com/upload',
filePath: file.path,
name: 'file',
formData: {
'fileName': file.name
},
success: (res) => {
const data = JSON.parse(res.data);
if (data.success) {
uploadTask.progress = 100;
uni.showToast({
title: '上传成功'
});
}
},
fail: (error) => {
uni.showToast({
title: '上传失败',
icon: 'none'
});
}
});
uploadTask.uploadTask = uploadRes;
// 监听上传进度
uploadRes.onProgressUpdate((res) => {
uploadTask.progress = res.progress;
});
} catch (error) {
console.error('Upload error:', error);
}
}
}
};
</script>
3. 文件下载与预览
实现文件下载功能,并支持常见格式的预览:
export default {
methods: {
async downloadFile(file) {
uni.showLoading({
title: '下载中...'
});
try {
const result = await uni.downloadFile({
url: file.url,
success: (res) => {
if (res.statusCode === 200) {
// 保存文件到本地
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
uni.hideLoading();
uni.showToast({
title: '下载成功'
});
this.$emit('download-complete', saveRes.savedFilePath);
}
});
}
}
});
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '下载失败',
icon: 'none'
});
}
},
previewFile(file) {
const extension = file.name.split('.').pop().toLowerCase();
const previewableTypes = ['pdf', 'jpg', 'jpeg', 'png', 'gif', 'txt'];
if (previewableTypes.includes(extension)) {
uni.navigateTo({
url: `/pages/index/file-preview?fileUrl=${encodeURIComponent(file.url)}&fileName=${encodeURIComponent(file.name)}`
});
} else {
uni.showModal({
title: '提示',
content: '该文件格式不支持预览,是否下载?',
success: (res) => {
if (res.confirm) {
this.downloadFile(file);
}
}
});
}
}
}
};
三、平台特定适配
1. 安卓文件系统权限处理
Android平台需要处理文件系统权限:
// #ifdef APP-PLUS
async checkAndroidPermission() {
try {
const result = await uni.authorize({
scope: 'scope.writePhotosAlbum'
});
return true;
} catch (error) {
// 权限未授予,请求权限
const settingResult = await uni.showModal({
title: '权限申请',
content: '需要存储权限才能保存文件',
confirmText: '去设置'
});
if (settingResult.confirm) {
uni.openAppAuthorizeSetting();
}
return false;
}
}
// #endif
2. iOS文件存储策略
iOS平台使用不同的文件存储策略:
// #ifdef APP-PLUS && OS_IOS
getIOSDocumentDirectory() {
return new Promise((resolve, reject) => {
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
resolve(fs.root.fullPath);
}, reject);
});
}
// #endif
四、性能优化与最佳实践
1. 虚拟列表优化
对于大量文件,使用虚拟列表提升性能:
// 使用uni-app的scroll-view结合自定义虚拟列表
<scroll-view
scroll-y
:style="{ height: scrollHeight + 'px' }"
@scroll="onScroll"
>
<view :style="{ height: totalHeight + 'px' }">
<view
v-for="item in visibleItems"
:key="item.id"
:style="{ transform: `translateY(${item.offset}px)` }"
>
<!-- 文件项内容 -->
</view>
</view>
</scroll-view>
2. 文件缓存机制
实现文件缓存以减少重复下载:
class FileCache {
constructor() {
this.cache = new Map();
this.maxSize = 50 * 1024 * 1024; // 50MB
this.currentSize = 0;
}
async getFile(url) {
if (this.cache.has(url)) {
return this.cache.get(url);
}
const file = await this.downloadAndCache(url);
return file;
}
async downloadAndCache(url) {
// 下载文件并添加到缓存
// 如果超过最大缓存大小,清理最旧的文件
while (this.currentSize > this.maxSize) {
this.removeOldest();
}
}
removeOldest() {
// 实现LRU缓存淘汰算法
}
}
五、测试与发布
1. 多平台测试策略
制定全面的测试计划:
- Android真机测试:文件权限、存储访问
- iOS真机测试:沙盒文件系统、相册访问
- 微信小程序测试:文件大小限制、API兼容性
- H5测试:浏览器文件API兼容性
2. 发布注意事项
各平台发布前的准备工作:
- Android:配置文件访问权限,处理动态权限申请
- iOS:配置相册访问描述,处理隐私权限
- 小程序:配置服务器域名,处理文件大小限制
- H5:配置HTTPS,处理浏览器兼容性
结语
通过本教程,我们完成了一个功能完整的跨平台文件管理器应用。这个项目展示了UniApp在处理复杂文件操作方面的强大能力,以及如何通过统一的API适配不同平台的特性。在实际开发中,还需要根据具体业务需求进一步完善错误处理、用户体验优化等功能。
UniApp的跨平台特性使得开发者可以用一套代码满足多个平台的需求,大大提高了开发效率。希望本文能够帮助读者深入理解UniApp文件操作的相关技术,并在实际项目中灵活运用。

