图片上传改造实施完成说明.md 11.2 KB

图片上传改造实施完成说明

实施日期:2025年1月
改造状态:✅ 已完成


一、改造完成内容

1.1 接口备份 ✅

已创建以下备份方法:

  1. Uploader_bak - 标准文件上传备份

    • 接口路径:POST /api/File/Uploader_bak/{type}
    • 位置:FileService.cs
  2. UploadBase64Image_bak - Base64图片上传备份

    • 接口路径:POST /api/File/UploadBase64Image_bak
    • 位置:FileService.cs
  3. 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(标准文件上传)

流程

  1. 保存文件到本地
  2. 判断是否需要上传到OSS
  3. 如果需要,从本地上传到OSS
  4. OSS上传成功 → 删除本地文件
  5. OSS上传失败 → 保留本地文件

返回值

  • OssSuccess:OSS是否上传成功
  • LocalPath:本地文件完整路径
  • OssPath:OSS文件路径

1.5.3 UploadBase64ToLocalThenOSS 方法

功能:先保存Base64数据到本地,再上传到OSS

流程

  1. 保存Base64数据到本地
  2. 从本地上传到OSS
  3. OSS上传成功 → 删除本地文件
  4. 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 正常流程测试

  1. OSS上传成功

    • ✅ 文件保存到本地
    • ✅ 文件上传到OSS
    • ✅ 本地文件被删除
    • ✅ 返回OSS URL
  2. 非OSS类型

    • ✅ 文件保存到本地
    • ✅ 不进行OSS上传
    • ✅ 返回本地完整URL

6.2 异常流程测试

  1. OSS上传失败(模拟OSS服务不可用):

    • ✅ 文件保存到本地
    • ✅ OSS上传失败
    • ✅ 本地文件保留
    • ✅ 返回本地完整URL(https://erp.lvqianmeiye.com/api/File/Image/...
  2. 本地保存失败(模拟磁盘满):

    • ✅ 本地保存失败
    • ✅ 抛出异常
    • ✅ 不进行OSS上传

6.3 URL验证测试

OSS成功时

  • 验证返回的URL是OSS地址
  • 验证URL可以正常访问

OSS失败时

  • 验证返回的URL是本地完整URL
  • 验证URL格式:https://erp.lvqianmeiye.com/api/File/Image/...
  • 验证URL可以正常访问(通过 GetImg 方法)

七、文件清单

7.1 修改的文件

  1. FileService.cs

    • 改造 Uploader 方法
    • 改造 UploadBase64Image 方法
    • 新增 GetLocalFileUrl 方法
    • 新增 UploadFileToLocalThenOSS 方法
    • 新增 UploadBase64ToLocalThenOSS 方法
    • 备份方法:Uploader_bakUploadBase64Image_bakUploadFileByType_bak
  2. KeyVariable.cs

    • 新增 LocalFileBaseUrl 属性
  3. 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 如果改造后出现问题

回滚步骤

  1. Uploader 方法内容替换为 Uploader_bak 的内容
  2. UploadBase64Image 方法内容替换为 UploadBase64Image_bak 的内容
  3. UploadFileByType 方法内容替换为 UploadFileByType_bak 的内容

备份方法位置

  • Uploader_bakFileService.cs
  • UploadBase64Image_bakFileService.cs
  • UploadFileByType_bakFileService.cs

十、后续优化建议

10.1 日志记录

建议添加日志记录:

  • OSS上传成功/失败日志
  • 本地文件删除成功/失败日志
  • 便于问题排查和监控

10.2 清理机制

建议实现定期清理机制:

  • 定期清理OSS上传失败后保留的本地文件
  • 可以设置保留时间(如:7天后自动删除)

10.3 监控告警

建议添加监控:

  • 监控本地存储空间使用率
  • 监控OSS上传失败率
  • 监控本地文件数量

十一、总结

11.1 改造完成

所有改造已完成

  • 接口备份 ✅
  • 配置项添加 ✅
  • 核心方法改造 ✅
  • 辅助方法创建 ✅
  • 异常处理完善 ✅

11.2 改造效果

  • ✅ 数据安全:本地有备份,OSS失败也能提供服务
  • ✅ 降级方案:OSS不可用时自动降级到本地存储
  • ✅ 完整URL:本地文件返回完整URL,便于前端使用
  • ✅ 可配置:本地URL可通过配置文件设置

改造完成时间:2025年1月
改造状态:✅ 已完成,等待测试验证