图片上传改造实施完成说明.md
11.2 KB
图片上传改造实施完成说明
实施日期:2025年1月
改造状态:✅ 已完成
一、改造完成内容
1.1 接口备份 ✅
已创建以下备份方法:
Uploader_bak- 标准文件上传备份- 接口路径:
POST /api/File/Uploader_bak/{type} - 位置:
FileService.cs
- 接口路径:
UploadBase64Image_bak- Base64图片上传备份- 接口路径:
POST /api/File/UploadBase64Image_bak - 位置:
FileService.cs
- 接口路径:
UploadFileByType_bak- 核心上传逻辑备份- 位置:
FileService.cs
- 位置:
1.2 配置项添加 ✅
配置文件:appsettings.json
新增配置项:
"NCC_App": {
"LocalFileBaseUrl": "https://erp.lvqianmeiye.com"
}
配置说明:
- 用于返回本地文件的完整访问地址
- 生产环境:
https://erp.lvqianmeiye.com - 开发环境:可配置为
http://localhost:2011或其他地址
1.3 KeyVariable 扩展 ✅
文件:KeyVariable.cs
新增属性:
/// <summary>
/// 本地文件访问基础URL(用于返回本地文件的完整访问地址)
/// </summary>
public static string LocalFileBaseUrl
{
get
{
var url = App.Configuration["NCC_App:LocalFileBaseUrl"]
?? App.Configuration["NCC_APP:LocalFileBaseUrl"]
?? App.Configuration["NCC_App:Domain"];
return string.IsNullOrEmpty(url) ? "http://localhost:2011" : url.TrimEnd('/');
}
}
1.4 核心方法改造 ✅
1.4.1 Uploader 方法
改造内容:
- ✅ 先上传到服务器本地
- ✅ 从服务器本地上传到OSS
- ✅ OSS上传成功 → 删除本地文件
- ✅ OSS上传失败 → 保留本地文件
- ✅ 返回完整URL(OSS成功用OSS URL,失败用本地完整URL)
关键代码:
// 先上传到本地,再上传到OSS
var (ossSuccess, localPath, ossPath) = await UploadFileToLocalThenOSS(
file,
_filePath, // 本地存储路径
ossFilePath, // OSS存储路径
_fileName,
forceStoreType);
// 根据OSS上传结果返回URL
if (type == "annexpic" && forceStoreType == "aliyun-oss")
{
if (ossSuccess)
{
fileUrl = await GetOSSAccessUrl(ossFilePath, _fileName);
}
else
{
// OSS上传失败,返回本地文件完整URL(降级方案)
fileUrl = GetLocalFileUrl(type, _fileName);
}
}
1.4.2 UploadBase64Image 方法
改造内容:
- ✅ 先保存Base64数据到服务器本地
- ✅ 从服务器本地上传到OSS
- ✅ OSS上传成功 → 删除本地文件
- ✅ OSS上传失败 → 保留本地文件
- ✅ 返回完整URL(OSS成功用OSS URL,失败用本地完整URL)
关键代码:
// 先保存到本地,再上传到OSS
var (ossSuccess, localPath, ossPath) = await UploadBase64ToLocalThenOSS(
imageData,
localFilePath, // 本地存储路径
ossFilePath, // OSS存储路径
fileName);
// 根据OSS上传结果返回URL
if (ossSuccess)
{
accessUrl = await GetOSSAccessUrl(ossFilePath, fileName);
}
else
{
// OSS上传失败,返回本地文件完整URL(降级方案)
accessUrl = GetLocalFileUrl(imageType, fileName);
}
1.5 新增辅助方法 ✅
1.5.1 GetLocalFileUrl 方法
功能:获取本地文件的完整访问URL
代码:
[NonAction]
private string GetLocalFileUrl(string type, string fileName)
{
var baseUrl = KeyVariable.LocalFileBaseUrl;
var relativePath = string.Format("/api/File/Image/{0}/{1}", type, fileName);
return $"{baseUrl}{relativePath}";
}
返回示例:
- 生产环境:
https://erp.lvqianmeiye.com/api/File/Image/annexpic/20250123_123.jpg - 开发环境:
http://localhost:2011/api/File/Image/annexpic/20250123_123.jpg
1.5.2 UploadFileToLocalThenOSS 方法
功能:先上传到本地,再上传到OSS(标准文件上传)
流程:
- 保存文件到本地
- 判断是否需要上传到OSS
- 如果需要,从本地上传到OSS
- OSS上传成功 → 删除本地文件
- OSS上传失败 → 保留本地文件
返回值:
OssSuccess:OSS是否上传成功LocalPath:本地文件完整路径OssPath:OSS文件路径
1.5.3 UploadBase64ToLocalThenOSS 方法
功能:先保存Base64数据到本地,再上传到OSS
流程:
- 保存Base64数据到本地
- 从本地上传到OSS
- OSS上传成功 → 删除本地文件
- OSS上传失败 → 保留本地文件
返回值:
OssSuccess:OSS是否上传成功LocalPath:本地文件完整路径OssPath:OSS文件路径
二、改造后的流程
2.1 标准文件上传流程
1. 验证文件类型
2. 生成文件路径和文件名
3. 【新增】先上传到服务器本地
4. 【新增】从服务器本地上传到OSS
5. 【新增】OSS上传成功 → 删除本地文件
6. 【新增】OSS上传失败 → 保留本地文件
7. 根据OSS上传结果返回URL:
- OSS成功:返回OSS访问URL(带签名)
- OSS失败:返回本地文件完整URL(https://erp.lvqianmeiye.com/api/File/Image/...)
8. 返回结果
2.2 Base64图片上传流程
1. 解析Base64数据
2. 验证图片格式
3. 生成文件路径和文件名
4. 【新增】先保存Base64数据到服务器本地
5. 【新增】从服务器本地上传到OSS
6. 【新增】OSS上传成功 → 删除本地文件
7. 【新增】OSS上传失败 → 保留本地文件
8. 根据OSS上传结果返回URL:
- OSS成功:返回OSS访问URL(带签名)
- OSS失败:返回本地文件完整URL(https://erp.lvqianmeiye.com/api/File/Image/...)
9. 返回结果
三、配置说明
3.1 配置文件位置
文件:netcore/src/Application/NCC.API/appsettings.json
3.2 配置项
{
"NCC_App": {
"LocalFileBaseUrl": "https://erp.lvqianmeiye.com"
}
}
3.3 环境配置
生产环境:
"LocalFileBaseUrl": "https://erp.lvqianmeiye.com"
开发环境:
"LocalFileBaseUrl": "http://localhost:2011"
测试环境:
"LocalFileBaseUrl": "http://erp_test.lvqianmeiye.com"
四、URL返回规则
4.1 OSS上传成功
返回URL格式:
https://lvqian-erip.oss-cn-chengdu.aliyuncs.com/2025/01/23/20250123_123.jpg?签名参数
特点:
- 带签名的临时访问URL(有效期24小时)
- 如果配置了自定义域名,使用自定义域名
4.2 OSS上传失败(降级方案)
返回URL格式:
https://erp.lvqianmeiye.com/api/File/Image/annexpic/20250123_123.jpg
特点:
- 完整的HTTP/HTTPS URL
- 通过
GetImg方法提供访问 - 本地文件保留,确保可以访问
五、异常处理
5.1 本地保存失败
处理方式:直接抛出异常,不进行OSS上传
异常信息:
文件保存到本地失败: {错误信息}
5.2 OSS上传失败
处理方式:
- 捕获异常,不抛出
- 保留本地文件
- 返回本地文件完整URL(降级方案)
日志记录(可选):
// 可以在这里添加日志记录:
// _logger?.LogError(ex, $"文件上传到OSS失败,保留本地文件: {localFullPath}");
5.3 OSS上传成功但删除本地文件失败
处理方式:
- 捕获异常,不抛出
- 不影响返回结果
- 返回OSS访问URL
日志记录(可选):
// 可以在这里添加日志记录:
// _logger?.LogWarning(ex, $"OSS上传成功但删除本地文件失败: {localFullPath}");
六、测试建议
6.1 正常流程测试
OSS上传成功:
- ✅ 文件保存到本地
- ✅ 文件上传到OSS
- ✅ 本地文件被删除
- ✅ 返回OSS URL
非OSS类型:
- ✅ 文件保存到本地
- ✅ 不进行OSS上传
- ✅ 返回本地完整URL
6.2 异常流程测试
OSS上传失败(模拟OSS服务不可用):
- ✅ 文件保存到本地
- ✅ OSS上传失败
- ✅ 本地文件保留
- ✅ 返回本地完整URL(
https://erp.lvqianmeiye.com/api/File/Image/...)
本地保存失败(模拟磁盘满):
- ✅ 本地保存失败
- ✅ 抛出异常
- ✅ 不进行OSS上传
6.3 URL验证测试
OSS成功时:
- 验证返回的URL是OSS地址
- 验证URL可以正常访问
OSS失败时:
- 验证返回的URL是本地完整URL
- 验证URL格式:
https://erp.lvqianmeiye.com/api/File/Image/... - 验证URL可以正常访问(通过
GetImg方法)
七、文件清单
7.1 修改的文件
FileService.cs- 改造
Uploader方法 - 改造
UploadBase64Image方法 - 新增
GetLocalFileUrl方法 - 新增
UploadFileToLocalThenOSS方法 - 新增
UploadBase64ToLocalThenOSS方法 - 备份方法:
Uploader_bak、UploadBase64Image_bak、UploadFileByType_bak
- 改造
KeyVariable.cs- 新增
LocalFileBaseUrl属性
- 新增
appsettings.json- 新增
LocalFileBaseUrl配置项
- 新增
八、注意事项
8.1 配置检查
✅ 必须配置 LocalFileBaseUrl:
- 生产环境:
https://erp.lvqianmeiye.com - 开发环境:
http://localhost:2011 - 测试环境:
http://erp_test.lvqianmeiye.com
8.2 本地存储空间
⚠️ 需要监控:
- 本地磁盘空间
- OSS上传失败后保留的本地文件数量
- 建议定期清理OSS上传失败后保留的本地文件
8.3 文件权限
✅ 确保:
- 应用有本地文件写入权限
- 应用有本地文件删除权限
- 应用有本地文件读取权限(用于上传到OSS)
8.4 路径安全
✅ 已处理:
- 使用
Path.Combine组合本地路径(防止路径遍历) - 使用正斜杠
/组合OSS路径
九、回滚方案
9.1 如果改造后出现问题
回滚步骤:
- 将
Uploader方法内容替换为Uploader_bak的内容 - 将
UploadBase64Image方法内容替换为UploadBase64Image_bak的内容 - 将
UploadFileByType方法内容替换为UploadFileByType_bak的内容
备份方法位置:
Uploader_bak:FileService.csUploadBase64Image_bak:FileService.csUploadFileByType_bak:FileService.cs
十、后续优化建议
10.1 日志记录
建议添加日志记录:
- OSS上传成功/失败日志
- 本地文件删除成功/失败日志
- 便于问题排查和监控
10.2 清理机制
建议实现定期清理机制:
- 定期清理OSS上传失败后保留的本地文件
- 可以设置保留时间(如:7天后自动删除)
10.3 监控告警
建议添加监控:
- 监控本地存储空间使用率
- 监控OSS上传失败率
- 监控本地文件数量
十一、总结
11.1 改造完成
✅ 所有改造已完成:
- 接口备份 ✅
- 配置项添加 ✅
- 核心方法改造 ✅
- 辅助方法创建 ✅
- 异常处理完善 ✅
11.2 改造效果
- ✅ 数据安全:本地有备份,OSS失败也能提供服务
- ✅ 降级方案:OSS不可用时自动降级到本地存储
- ✅ 完整URL:本地文件返回完整URL,便于前端使用
- ✅ 可配置:本地URL可通过配置文件设置
改造完成时间:2025年1月
改造状态:✅ 已完成,等待测试验证