企业级图片上传处理函数实现
# 企业级图片上传处理函数实现
下面是一个企业级的图片上传处理函数,具有高度可配置性、错误处理和预览功能:
```typescript
import { QNotifyCreateOptions } from 'quasar';
/**
* 企业级图片上传处理函数
*
* @param file - 上传的文件对象
* @param options - 配置选项
* @returns 预览URL字符串或null
*/
export function processImageForUpload(
file: File,
options: ImageUploadOptions = {}
): Promise<string | null> {
return new Promise((resolve, reject) => {
// 合并默认配置
const config: Required<ImageUploadOptions> = {
validTypes: ['image/jpeg', 'image/png', 'image/webp', 'image/gif'],
maxSize: 2.5 * 1024 * 1024, // 2.5MB
maxDimensions: { width: 4096, height: 4096 },
onError: defaultErrorHandler,
onSuccess: () => {},
...options
};
// 验证文件存在性
if (!file) {
const error = createErrorObject('no-file', '未选择文件');
config.onError(error);
reject(error);
return;
}
// 验证文件类型
if (!config.validTypes.includes(file.type)) {
const error = createErrorObject(
'invalid-type',
'不支持的图片格式',
`支持的类型: ${config.validTypes.join(', ')}`
);
config.onError(error);
reject(error);
return;
}
// 验证文件大小
if (file.size > config.maxSize) {
const error = createErrorObject(
'size-exceeded',
'文件过大',
`最大允许: ${formatBytes(config.maxSize)},当前: ${formatBytes(file.size)}`
);
config.onError(error);
reject(error);
return;
}
// 创建文件预览
const reader = new FileReader();
reader.onload = (e) => {
const dataURL = e.target?.result as string;
// 验证图片尺寸
validateImageDimensions(dataURL, config.maxDimensions)
.then(() => {
config.onSuccess(dataURL);
resolve(dataURL);
})
.catch((dimensionError) => {
config.onError(dimensionError);
reject(dimensionError);
});
};
reader.onerror = () => {
const error = createErrorObject(
'read-error',
'文件读取失败',
'无法创建图片预览'
);
config.onError(error);
reject(error);
};
reader.readAsDataURL(file);
});
}
/**
* 验证图片尺寸是否符合要求
*
* @param dataURL - 图片的DataURL
* @param maxDimensions - 最大允许尺寸
*/
function validateImageDimensions(
dataURL: string,
maxDimensions: { width: number; height: number }
): Promise<void> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
if (img.width > maxDimensions.width || img.height > maxDimensions.height) {
const error = createErrorObject(
'dimension-exceeded',
'图片尺寸过大',
`最大尺寸: ${maxDimensions.width}×${maxDimensions.height}px, 当前: ${img.width}×${img.height}px`
);
reject(error);
} else {
resolve();
}
};
img.onerror = () => {
const error = createErrorObject(
'load-error',
'图片加载失败',
'无法验证图片尺寸'
);
reject(error);
};
img.src = dataURL;
});
}
/**
* 创建错误对象
*/
function createErrorObject(
type: ImageErrorType,
message: string,
caption?: string
): ImageUploadError {
return {
type,
message,
caption,
timestamp: new Date().toISOString()
};
}
/**
* 默认错误处理器(使用Quasar通知)
*/
function defaultErrorHandler(error: ImageUploadError) {
// 在实际应用中,这里可以使用Quasar的$q.notify或其他UI通知
console.error(`[Image Upload Error] ${error.type}: ${error.message}`, error.caption);
// 模拟Quasar通知
const notifyOptions: QNotifyCreateOptions = {
type: 'negative',
message: error.message,
caption: error.caption,
position: 'top',
timeout: 5000,
actions: [{ icon: 'close', color: 'white' }]
};
// 实际使用中: $q.notify(notifyOptions);
console.log('显示通知:', notifyOptions);
}
/**
* 格式化字节大小
*
* @param bytes - 字节大小
* @param decimals - 小数位数
*/
function formatBytes(bytes: number, decimals = 2): string {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
/**
* 类型定义
*/
interface ImageUploadOptions {
/** 允许的文件类型 */
validTypes?: string[];
/** 最大文件大小(字节) */
maxSize?: number;
/** 最大图片尺寸 */
maxDimensions?: { width: number; height: number };
/** 错误处理回调 */
onError?: (error: ImageUploadError) => void;
/** 成功处理回调 */
onSuccess?: (previewUrl: string) => void;
}
type ImageErrorType =
| 'no-file'
| 'invalid-type'
| 'size-exceeded'
| 'dimension-exceeded'
| 'read-error'
| 'load-error';
interface ImageUploadError {
type: ImageErrorType;
message: string;
caption?: string;
timestamp: string;
}
```
## 使用示例
```typescript
// 在Vue组件中使用
import { processImageForUpload } from '@/utils/imageUploader';
// 在Quasar项目中
export default defineComponent({
setup() {
const avatarFile = ref<File | null>(null);
const newAvatarPreview = ref<string | null>(null);
const handleImageUpload = async (file: File) => {
try {
const previewUrl = await processImageForUpload(file, {
maxSize: 3 * 1024 * 1024, // 3MB
validTypes: ['image/jpeg', 'image/png', 'image/webp'],
maxDimensions: { width: 3000, height: 3000 },
onError: (error) => {
// 使用Quasar通知
$q.notify({
type: 'negative',
message: error.message,
caption: error.caption,
position: 'top',
timeout: 5000,
actions: [{ icon: 'close', color: 'white' }]
});
}
});
newAvatarPreview.value = previewUrl;
} catch (error) {
console.error('图片上传处理失败:', error);
avatarFile.value = null;
newAvatarPreview.value = null;
}
};
return {
avatarFile,
newAvatarPreview,
handleImageUpload
};
}
});
```
## 企业级功能亮点
1. **高度可配置性**:
- 支持自定义文件类型、大小限制和尺寸限制
- 可配置错误处理和成功回调
- 默认值合理设置,开箱即用
2. **全面的错误处理**:
- 6种不同的错误类型分类
- 详细的错误信息和描述
- 错误时间戳记录
- 内置默认错误处理器
3. **高级验证功能**:
- 文件类型验证
- 文件大小验证
- 图片尺寸验证
- 文件读取错误处理
4. **Promise API**:
- 使用Promise提供现代化异步处理
- 支持async/await语法
- 清晰的解决/拒绝路径
5. **实用工具函数**:
- 字节大小格式化
- 错误对象工厂函数
- 图片尺寸验证器
6. **完善的类型定义**:
- 所有参数和返回类型都有明确类型
- 错误类型枚举
- 配置选项接口
7. **模块化设计**:
- 核心功能与UI通知解耦
- 可替换的默认错误处理器
- 独立的功能模块
8. **安全考虑**:
- 防止过大的图片占用内存
- 限制图片尺寸防止DoS攻击
- 安全的文件读取处理
这个企业级图片上传处理函数提供了全面的验证和处理功能,可以轻松集成到任何前端项目中,特别适合需要严格文件验证的企业级应用场景。