一、前言
在移动端开发中,文件上传是常见的功能需求。本文将通过Uniapp框架,详细讲解如何实现支持多类型文件(图片、视频、文档等)的上传功能,并解决跨平台兼容性问题😄😄😄。
二、技术方案
2.1 核心API
Uniapp提供了以下关键API:
uni.chooseFile
:文件选择uni.uploadFile
:文件上传uni.getFileInfo
:获取文件信息
2.2 平台差异处理
平台 | 文件选择方式 | 限制说明 |
---|---|---|
H5 | <input type="file"> |
依赖浏览器实现 |
微信小程序 | wx.chooseMessageFile |
需配置合法域名 |
App | plus.io 文件系统 |
需处理本地文件路径 |
三、完整实现代码
3.1 文件选择器封装
javascript
// 多类型文件选择
function chooseFiles(fileType = 'all') {
return new Promise((resolve, reject) => {
const extnameMap = {
image: ['png', 'jpg', 'jpeg'],
video: ['mp4', 'mov'],
document: ['pdf', 'doc', 'docx', 'xls']
};
uni.chooseFile({
count: 5, // 最大选择数量
extension: fileType === 'all' ? [] : extnameMap[fileType],
success: res => {
const files = res.tempFiles.map(item => ({
path: item.path,
name: item.name,
size: item.size,
type: item.type
}));
resolve(files);
},
fail: err => reject(err)
});
});
}
3.2 文件上传核心方法
javascript
// 上传文件到服务器
async function uploadFile(file) {
try {
const formData = {
userId: '123',
fileType: file.type
};
const res = await uni.uploadFile({
url: 'https://api.example.com/upload',
filePath: file.path,
name: 'file',
formData,
header: {
'Authorization': 'Bearer token'
}
});
return JSON.parse(res[1].data);
} catch (error) {
console.error('上传失败:', error);
throw error;
}
}
3.3 进度显示实现
javascript
// 带进度上传
function uploadWithProgress(file, onProgress) {
return new Promise((resolve, reject) => {
const task = uni.uploadFile({
url: 'https://api.example.com/upload',
filePath: file.path,
name: 'file',
success: (res) => resolve(JSON.parse(res.data)),
fail: reject,
complete: () => task.offProgressUpdate()
});
task.onProgressUpdate((res) => {
onProgress && onProgress({
progress: res.progress,
totalBytesSent: res.totalBytesSent,
totalBytesExpectedToSend: res.totalBytesExpectedToSend
});
});
});
}
四、界面实现示例
html
<template>
<view class="upload-container">
<button @click="chooseFiles">选择文件</button>
<view class="preview-list">
<view v-for="(file, index) in files" :key="index" class="file-item">
<image v-if="file.type.startsWith('image/')" :src="file.path" mode="aspectFit"/>
<video v-else-if="file.type.startsWith('video/')" :src="file.path"/>
<view v-else class="document-icon">
<text>{{ getFileExt(file.name) }}</text>
</view>
<progress :percent="file.progress" show-info />
</view>
</view>
</view>
</template>
<style>
/* 文件预览样式 */
.preview-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
margin-top: 20px;
}
.file-item {
position: relative;
width: 100px;
height: 100px;
border: 1px dashed #ddd;
}
.document-icon {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background: #f0f0f0;
}
</style>
五、服务端配合建议
5.1 文件接收配置(Node.js示例)
javascript
const multer = require('multer');
const storage = multer.diskStorage({
destination: 'uploads/',
filename: (req, file, cb) => {
const ext = path.extname(file.originalname);
cb(null, `${Date.now()}${ext}`);
}
});
const upload = multer({
storage,
limits: {
fileSize: 1024 * 1024 * 50 // 50MB
},
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png', 'video/mp4', 'application/pdf'];
cb(null, allowedTypes.includes(file.mimetype));
}
});
router.post('/upload', upload.single('file'), (req, res) => {
// 处理上传成功逻辑
});
六、注意事项🐛
- 文件大小限制:需同时在前端和服务端设置
- 格式验证:不能仅依赖前端验证
- 安全处理 :
- 重命名存储文件
- 扫描恶意文件
- 设置访问权限
- 性能优化 :
- 图片压缩(可使用uni.compressImage)
- 分片上传大文件
- 断点续传