在.NET Core Web Api中使用阿里云OSS

1.安装Aliyun.OSS.SDK.NetCore

2.在appsettings.json里配置OSS相关参数

cs 复制代码
{
  
  "AliyunOss": {
    "Endpoint": "Bucket地域", // 与Bucket地域一致
    "BucketName": "Bucket名称", // 你的Bucket名称
    "AccessKeyId": "AccessKey ID", // 你的AccessKey ID
    "AccessKeySecret": "AccessKey Secret" // 你的AccessKey Secret
  }
}

9.3.创建配置模型类

cs 复制代码
namespace web01.Configurations
{
    public class AliyunOssSettings
    {
        public string Endpoint { get; set; } = string.Empty;
        public string AccessKeyId { get; set; } = string.Empty;
        public string AccessKeySecret { get; set; } = string.Empty;
        public string BucketName { get; set; } = string.Empty;
    }
}

9.4.创建OSS工具类

cs 复制代码
using Aliyun.OSS;
using Aliyun.OSS.Common;
using Microsoft.Extensions.Logging;
using System;
using System.IO;

namespace YourProject.Utils
{
    public class AliOssUtil
    {
        private readonly string _endpoint;
        private readonly string _accessKeyId;
        private readonly string _accessKeySecret;
        private readonly string _bucketName;
        private readonly ILogger<AliOssUtil> _logger;

        public AliOssUtil(
            string endpoint,
            string accessKeyId,
            string accessKeySecret,
            string bucketName,
            ILogger<AliOssUtil> logger)
        {
            // 步骤1:先给字段赋值(避免null引用)
            _endpoint = endpoint ?? throw new ArgumentNullException(nameof(endpoint));
            _accessKeyId = accessKeyId ?? throw new ArgumentNullException(nameof(accessKeyId));
            _accessKeySecret = accessKeySecret ?? throw new ArgumentNullException(nameof(accessKeySecret));
            _bucketName = bucketName ?? throw new ArgumentNullException(nameof(bucketName));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            // 步骤2:再记录日志
            _logger.LogInformation("AliOssUtil初始化:Endpoint={Endpoint}, Bucket={Bucket}", _endpoint, _bucketName);
        }

        /// <summary>
        /// 上传文件到阿里云OSS,返回访问URL
        /// </summary>
        public string UploadFile(IFormFile file)
        {
            _logger.LogInformation("开始上传文件,文件名:{FileName}, 大小:{FileSize}KB", file.FileName, file.Length / 1024f);
            if (file == null || file.Length == 0)
            {
                throw new ArgumentException("文件不能为空", nameof(file));
            }

            // 生成唯一文件名(避免重复)
            string uniqueFileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
            // 定义OSS中的文件路径(如:"uploads/20251026/xxx.jpg")
            string objectName = $"uploads/{DateTime.Now:yyyyMMdd}/{uniqueFileName}";

            try
            {
                // 创建OSS客户端
                var ossClient = new OssClient(_endpoint, _accessKeyId, _accessKeySecret);

                // 读取文件流并上传
                using var stream = file.OpenReadStream();
                if (stream == null || stream.Length == 0)
                {
                    _logger.LogError("文件流为空");
                    throw new ArgumentException("文件流无效", nameof(file));
                }
                ossClient.PutObject(_bucketName, objectName, stream);

                // 生成可访问的URL
                string fileUrl = $"https://{_bucketName}.{_endpoint}/{objectName}";
                _logger.LogInformation("文件上传成功,URL:{FileUrl}", fileUrl);
                return fileUrl;
            }
            catch (OssException oe)
            {
                _logger.LogError(oe, "OSS服务端异常:Code={Code}, Message={Message}", oe.ErrorCode, oe.Message);
                throw new Exception($"OSS上传失败:{oe.ErrorCode} - {oe.Message}", oe);
            }
            catch (ClientException ce)
            {
                _logger.LogError(ce, "OSS客户端异常:Message={Message}", ce.Message);
                throw new Exception($"OSS客户端错误:{ce.Message}", ce);
            }
        }
    }
}

9.5.在Program.cs中注册服务

cs 复制代码
var builder = WebApplication.CreateBuilder(args);
// 读取OSS配置
builder.Services.Configure<AliyunOssSettings>(builder.Configuration.GetSection("AliyunOss"));

// 注册OSS客户端(单例模式)
builder.Services.AddSingleton(sp =>
{
    var settings = sp.GetRequiredService<IOptions<AliyunOssSettings>>().Value;
    return new OssClient(settings.Endpoint, settings.AccessKeyId, settings.AccessKeySecret);
});

builder.Services.AddControllers();

9.6.控制器实现

cs 复制代码
using Aliyun.OSS;
using Aliyun.OSS.Common;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using web01.Configurations;
using web01.services;
using web01.Utils;
using YourProject.Utils;

namespace web01.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class FileUploadController : ControllerBase
    {
        private readonly OssClient _ossClient;
        private readonly AliyunOssSettings _ossSettings;

        public FileUploadController(OssClient ossClient, IOptions<AliyunOssSettings> ossSettings)
        {
            _ossClient = ossClient;
            _ossSettings = ossSettings.Value;
        }

        [HttpPost("upload")]
        public IActionResult UploadFile(IFormFile file)
        {
            if (file == null || file.Length == 0)
            {
                return BadRequest("请选择要上传的文件");
            }

            try
            {
                var objectKey = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";

                using (var stream = file.OpenReadStream())
                {
                    // 调用同步方法 PutObject(无 Async 后缀)
                    _ossClient.PutObject(_ossSettings.BucketName, objectKey, stream);
                }

                var fileUrl = $"https://{_ossSettings.BucketName}.{_ossSettings.Endpoint}/{objectKey}";

                return Ok(new
                {
                    success = true,
                    url = fileUrl,
                    message = "文件上传成功"
                });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new
                {
                    success = false,
                    message = "文件上传失败",
                    error = ex.Message
                });
            }
        }
    }
}
相关推荐
William_cl17 分钟前
C# ASP.NET 分层架构实战:BLL (Service) 业务层从入门到封神(规范 + 避坑)
架构·c#·asp.net
qq_454245031 小时前
图数据标准化与智能去重框架:设计与实现解析
数据结构·架构·c#·图论
CSharp精选营2 小时前
C# 如何减少代码运行时间:7 个实战技巧
性能优化·c#·.net·技术干货·实战技巧
hhh3u3u3u15 小时前
Visual C++ 6.0中文版安装包下载教程及win11安装教程
java·c语言·开发语言·c++·python·c#·vc-1
加号315 小时前
【C#】实现沃德普线光控制器通信控制(附完整源码)
开发语言·c#
lzhdim16 小时前
SharpCompress:跨平台的 C# 压缩与解压库
开发语言·c#
祖传F8717 小时前
quickbi数据集数据查询时间字段显示正确,仪表板不显示
数据库·sql·阿里云
~plus~18 小时前
.NET 8 C# 委托与事件实战教程
网络·c#·.net·.net 8·委托与事件·c#进阶
beyond谚语19 小时前
接口&抽象类
c#·接口隔离原则·抽象类
新手小新19 小时前
C#学习笔记1-在VS CODE部署C#开发环境
笔记·学习·c#