在移动应用开发中,图片上传功能是一个非常常见的需求。本文将详细介绍如何在UniApp框架下实现一个功能完善的多图选择上传组件,并重点关注鸿蒙系统的适配与优化。
在开发多图上传功能时,我们需要考虑以下几个关键点:
首先,我们实现一个基础的图片选择器组件:
×
{{ item.progress }}%
点击选择
为了优化上传性能,我们实现了智能压缩功能:
// utils/imageProcessor.js
export const compress = async (path, options = {}) => {
const {
quality = 80,
maxWidth = 1920,
maxHeight = 1920
} = options
// 获取图片信息
const imageInfo = await uni.getImageInfo({
src: path
})
// 计算压缩后的尺寸
let { width, height } = imageInfo
const ratio = Math.min(
maxWidth / width,
maxHeight / height,
1
)
width = Math.floor(width * ratio)
height = Math.floor(height * ratio)
// 压缩图片
return new Promise((resolve, reject) => {
// #ifdef HARMONY-OS
// 使用HMS Image Kit压缩
const imageKit = getHMSImageKit()
imageKit.compressImage({
uri: path,
format: 'JPEG',
quality,
targetWidth: width,
targetHeight: height
})
.then(resolve)
.catch(reject)
// #endif
// #ifndef HARMONY-OS
uni.compressImage({
src: path,
quality,
width,
height,
success: resolve,
fail: reject
})
// #endif
})
}
实现一个可靠的上传队列管理器:
// utils/uploader.js
class UploadQueue {
constructor(options = {}) {
this.queue = []
this.concurrent = options.concurrent || 3
this.running = 0
this.retryTimes = options.retryTimes || 3
this.retryDelay = options.retryDelay || 1000
}
add(task) {
this.queue.push({
...task,
retryCount: 0
})
this.check()
}
async check() {
if (this.running >= this.concurrent) return
const task = this.queue.find(t => !t.isRunning)
if (!task) return
this.running++
task.isRunning = true
try {
await this.runTask(task)
} catch (error) {
if (task.retryCount < this.retryTimes) {
task.retryCount++
task.isRunning = false
await this.delay(this.retryDelay)
this.check()
} else {
task.onError && task.onError(error)
}
}
this.running--
this.check()
}
async runTask(task) {
const formData = new FormData()
formData.append('file', task.file)
const response = await fetch(task.url, {
method: 'POST',
body: formData,
headers: task.headers
})
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`)
}
const result = await response.json()
task.onSuccess && task.onSuccess(result)
}
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
}
export const uploadToServer = (filePath, options = {}) => {
return new Promise((resolve, reject) => {
const uploader = new UploadQueue()
uploader.add({
file: filePath,
url: options.url || '/api/upload',
headers: options.headers,
onProgress: options.onProgress,
onSuccess: resolve,
onError: reject
})
})
}
在鸿蒙系统上,我们利用HMS Image Kit提供的能力:
export class HMSImageManager {
constructor() {
this.imageKit = null
}
async init() {
try {
// 初始化HMS Image Kit
const hms = await this.getHMSCore()
this.imageKit = hms.imageKit({
compressFormat: 'JPEG',
compressQuality: 80
})
return true
} catch (error) {
console.error('HMS Image Kit初始化失败:', error)
return false
}
}
async pickImages(options) {
if (!this.imageKit) await this.init()
return this.imageKit.pickImages({
...options,
mediaType: ['image/jpeg', 'image/png'],
selectionMode: 'multiple'
})
}
async compressImage(options) {
if (!this.imageKit) await this.init()
return this.imageKit.compressImage(options)
}
}
针对鸿蒙系统的特点,我们进行了一些性能优化:
const optimizeForHMS = {
// 图片缓存策略
cacheStrategy: {
mode: 'memory_first',
maxMemorySize: 20 * 1024 * 1024, // 20MB
maxDiskSize: 100 * 1024 * 1024 // 100MB
},
// 预加载配置
preloadConfig: {
preloadCount: 3,
preloadDistance: 2
},
// 内存管理
memoryManagement: {
clearThreshold: 0.8,
autoRelease: true
}
}
通过以上实现,我们的图片上传组件具备以下特点:
在实际应用中,我们还可以根据具体需求进行以下优化:
随着鸿蒙生态的发展,我们可以期待:
图片上传是一个看似简单但实际涉及诸多技术点的功能,需要我们在性能、体验和可靠性之间找到平衡。通过本文的实践,相信大家已经掌握了实现一个专业图片上传组件的核心要点。在实际开发中,还需要根据具体场景进行调整和优化。
希望本文对大家有所帮助,也欢迎在评论区分享你的开发经验!