Sage.CloudStorage.Qiniu 1.0.0.3

dotnet add package Sage.CloudStorage.Qiniu --version 1.0.0.3
                    
NuGet\Install-Package Sage.CloudStorage.Qiniu -Version 1.0.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Sage.CloudStorage.Qiniu" Version="1.0.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sage.CloudStorage.Qiniu" Version="1.0.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Sage.CloudStorage.Qiniu" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Sage.CloudStorage.Qiniu --version 1.0.0.3
                    
#r "nuget: Sage.CloudStorage.Qiniu, 1.0.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Sage.CloudStorage.Qiniu@1.0.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Sage.CloudStorage.Qiniu&version=1.0.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Sage.CloudStorage.Qiniu&version=1.0.0.3
                    
Install as a Cake Tool

Sage.CloudStorage.Qiniu - 现代化七牛云存储 .NET SDK

简介

Sage.CloudStorage.Qiniu 是一个基于 .NET 平台的现代化七牛云存储 SDK,采用完全异步设计,提供了对七牛云对象存储、CDN 等服务的简单易用的 API 封装。该库基于 Sage.Http 构建,具有高性能、可扩展的七牛云服务访问能力,特别适合企业级应用和大文件处理场景。

核心优势

  • 现代化API设计:完全异步,符合.NET最佳实践
  • 模块化架构:各组件职责明确,易于扩展和维护
  • 丰富的事件机制:提供上传进度通知和完成事件
  • 智能上传策略:自动选择最佳上传方式和分片大小
  • 完善的错误处理:提供详细的错误信息和恢复机制

功能特性

  • 完整的对象存储支持:上传、下载、管理、删除等操作
  • 高级上传功能
    • 智能分片上传(自动优化分片大小)
    • 断点续传支持
    • 并发控制
    • 实时进度监控
  • CDN管理:刷新、预取、带宽查询、日志下载
  • 数据处理:图片处理、音视频转码等
  • 批量操作:批量上传、删除等
  • AOT编译:使用了源生成,支持AOT,提升性能

安装

dotnet add package Sage.CloudStorage.Qiniu

快速入门

初始化

using Sage.CloudStorage.Qiniu;
using Sage.CloudStorage.Qiniu.Models;
using Sage.CloudStorage.Qiniu.Config;

// 创建七牛云客户端
var httpManager = new HttpRequestManager(HttpClientSingleton.Instance);
var client = new QiniuClient("your-access-key", "your-secret-key", httpManager);

// 使用自定义的HttpRequestManager
using Sage.Http.Core;

// 创建自定义的HttpRequestManager并进行配置
var httpManager = new HttpRequestManager(HttpClientSingleton.Instance);
// 可以对httpManager进行自定义配置

// 使用配置好的HttpRequestManager创建七牛云客户端
var clientWithConfig = new QiniuClient("your-access-key", "your-secret-key", httpManager, new QiniuConfig
{
    UseHttps = true,
    BlockSize = 4 * 1024 * 1024
});

自定义配置

// 创建高级配置
var config = new QiniuConfig
{
    // 基础配置
    UseHttps = true,                           // 使用HTTPS协议
    BlockSize = 4 * 1024 * 1024,               // 4MB分片大小
    ConnectionTimeout = 30000,                 // 连接超时时间(毫秒)
    ReadTimeout = 60000,                       // 读取超时时间(毫秒)
    WriteTimeout = 60000,                      // 写入超时时间(毫秒)
    MaxRetryTimes = 3,                         // 最大重试次数
    
    // 区域配置
    AutoSelectUploadHost = true,               // 自动选择最优上传域名
    // 或手动指定域名
    // UpHost = "upload.qiniup.com",          // 自定义上传域名
    
    // 高级配置
    UseCdnForDownload = true,                  // 使用CDN加速下载
    ChunkUploadConcurrency = 3,                // 分片上传的并发数
    ProgressCallbackInterval = 1024 * 1024     // 上传进度回调间隔(字节)
};

// 创建客户端
var client = new QiniuClient("your-access-key", "your-secret-key", config);

模块化访问

Sage.Qiniu采用模块化设计,每个功能领域由专门的管理器类处理:

// 存储桶操作
var bucketManager = client.Bucket;

// 文件上传
var uploadManager = client.Upload;

// 文件下载
var downloadManager = client.Download;

// CDN管理
var cdnManager = client.Cdn;

// 数据处理
var operationManager = client.Operation;

功能示例

数据处理操作

// 持久化数据处理
var pfopResult = await client.Operation.PfopAsync(
    "bucket-name",
    "file-key",
    "avthumb/mp4/s/640x360/vb/1.25m",
    "example.com",
    true);

// 查询持久化处理状态
var prefopResult = await client.Operation.PrefopAsync(pfopResult.PersistentId);

// 对URL进行数据处理
var processedData = await client.Operation.DfopAsync(
    "http://domain.com/file-key",
    "imageView2/1/w/200/h/200");

// 对本地文件进行数据处理
var processedFile = await client.Operation.DfopAsync(
    "local-file-path",
    "imageView2/1/w/200/h/200",
    isLocalFile: true);

// 对文本内容进行数据处理
string text = "Hello, Qiniu!";
var processedText = await client.Operation.DfopAsync(
    text,
    "qrcode/0",
    isText: true);

存储桶操作

// 获取存储桶列表
var buckets = await client.Bucket.GetBucketsAsync();

// 获取文件信息
var fileInfo = await client.Bucket.GetFileInfoAsync("bucket-name", "file-key");

// 列举文件
var files = await client.Bucket.ListFilesAsync("bucket-name", prefix: "prefix-", limit: 100);

// 删除文件
bool success = await client.Bucket.DeleteFileAsync("bucket-name", "file-key");

// 复制文件
bool success = await client.Bucket.CopyFileAsync("src-bucket", "src-key", "dest-bucket", "dest-key");

// 移动文件
bool success = await client.Bucket.MoveFileAsync("src-bucket", "src-key", "dest-bucket", "dest-key");

文件上传

简单上传

适用于小文件(<10MB)的快速上传:

// 简单上传文件
var result = await client.Upload.UploadFileAsync(
    filePath: "C:\\path\\to\\image.jpg", 
    key: "images/photo.jpg", 
    bucket: "my-bucket");

Console.WriteLine($"上传成功: {result.Key}, 哈希值: {result.Hash}");
带进度的上传

实时监控上传进度:

// 创建进度回调
var progress = new Progress<double>(percent => 
{
    Console.WriteLine($"上传进度: {percent:P2}");
    // 更新UI进度条
    // progressBar.Value = (int)(percent * 100);
});

// 上传文件并监控进度
var result = await client.Upload.UploadFileAsync(
    filePath: "C:\\path\\to\\video.mp4",
    key: "videos/intro.mp4",
    bucket: "my-bucket",
    progress: progress);
使用自定义上传策略

控制上传行为和文件属性:

// 创建自定义上传策略
var policy = new UploadPolicy
{
    // 基本设置
    Scope = "my-bucket:videos/intro.mp4",  // 指定上传空间和文件名
    Deadline = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds(),  // 上传凭证有效期
    
    // 文件属性设置
    MimeLimit = "video/*",  // 限制文件类型
    FsizeLimit = 500 * 1024 * 1024,  // 限制文件大小(500MB)
    
    // 回调设置
    CallbackUrl = "https://api.example.com/qiniu/callback",  // 回调URL
    CallbackBody = "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"size\":$(fsize),\"bucket\":\"$(bucket)\"}",  // 回调内容
    CallbackBodyType = "application/json",  // 回调格式
    
    // 返回内容设置
    ReturnBody = "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"size\":$(fsize),\"width\":$(imageInfo.width),\"height\":$(imageInfo.height)}"
};

// 使用自定义策略上传
var result = await client.Upload.UploadFileAsync(
    filePath: "C:\\path\\to\\video.mp4",
    key: "videos/intro.mp4",
    bucket: "my-bucket",
    policy: policy);
上传字节数组或内存流

直接上传内存中的数据:

// 上传字节数组
byte[] imageData = File.ReadAllBytes("C:\\path\\to\\image.jpg");
var result = await client.Upload.UploadDataAsync(
    data: imageData,
    key: "images/memory-image.jpg",
    bucket: "my-bucket");

// 上传内存流
using var stream = new MemoryStream();
// 向stream写入数据...
stream.Position = 0;
result = await client.Upload.UploadStreamAsync(
    stream: stream,
    key: "files/memory-data.bin",
    bucket: "my-bucket");
智能分片上传

自动处理大文件上传,内部优化分片大小和并发:

// 导入分片上传服务
using Sage.CloudStorage.Qiniu.Upload;

// 创建分片上传服务
var multipartService = new QiniuMultipartUploadService(
    httpManager: new Sage.Http.Core.HttpRequestManager(),
    qiniuKey: new QiniuKey("your-access-key", "your-secret-key"));

// 注册进度事件
multipartService.ProgressChanged += (sender, e) => 
{
    Console.WriteLine($"上传进度: {e.Percent:P2}, 已上传: {e.BytesUploaded}, 总大小: {e.TotalBytes}");
};

// 注册完成事件
multipartService.UploadCompleted += (sender, e) => 
{
    if (e.IsSuccess)
    {
        Console.WriteLine($"上传成功: {e.Key}, 哈希值: {e.Hash}, 耗时: {e.Duration.TotalSeconds:F1}秒");
    }
    else
    {
        Console.WriteLine($"上传失败: {e.ErrorMessage}");
    }
};

// 配置上传选项
var options = new UploadOptions
{
    ChunkSize = 4 * 1024 * 1024,  // 4MB分片,也可以不指定使用智能分片
    MaxConcurrency = 3,           // 最大并发数
    EnableConsoleLog = true        // 启用控制台日志
};

// 执行分片上传
var result = await multipartService.UploadFileAsync(
    filePath: "C:\\path\\to\\large-video.mp4",
    bucket: "my-bucket",
    key: "videos/large-video.mp4",
    options: options);
批量上传

一次性上传多个文件:

// 准备文件列表
var files = Directory.GetFiles("C:\\path\\to\\images", "*.jpg");

// 定义文件名生成器
string KeyGenerator(string filePath) => $"images/{Path.GetFileName(filePath)}";

// 定义上传策略生成器(可选)
UploadPolicy? PolicyGenerator(string filePath) => new UploadPolicy
{
    Scope = $"my-bucket:{KeyGenerator(filePath)}",
    Deadline = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds()
};

// 配置批量上传选项
var options = new UploadOptions
{
    BatchConcurrency = 5,  // 同时上传5个文件
    EnableConsoleLog = true
};

// 执行批量上传
var results = await multipartService.UploadBatchAsync(
    filePaths: files,
    bucket: "my-bucket",
    keyGenerator: KeyGenerator,
    policyGenerator: PolicyGenerator,
    options: options);

// 处理结果
foreach (var item in results)
{
    if (item.IsSuccess)
    {
        Console.WriteLine($"文件 {item.FilePath} 上传成功,Key: {item.Key}");
    }
    else
    {
        Console.WriteLine($"文件 {item.FilePath} 上传失败: {item.ErrorMessage}");
    }
}

### 文件下载

#### 下载私有资源

七牛云私有资源需要签名才能访问:

```csharp
// 创建私有资源下载URL(有效期1小时)
string privateUrl = client.Download.CreatePrivateUrl(
    url: "http://example.com/my-bucket/documents/report.pdf", 
    expireSeconds: 3600);

Console.WriteLine($"下载链接: {privateUrl}");
// 输出: http://example.com/my-bucket/documents/report.pdf?e=1630000000&token=abcdef...
下载到本地文件

将文件直接下载到本地磁盘:

// 下载公开资源
bool success = await client.Download.DownloadToFileAsync(
    url: "http://example.com/my-bucket/images/photo.jpg",
    saveToPath: "C:\\Downloads\\photo.jpg");

// 下载私有资源
success = await client.Download.DownloadToFileAsync(
    url: "http://example.com/my-bucket/documents/report.pdf",
    saveToPath: "C:\\Downloads\\report.pdf",
    isPrivate: true);  // 自动添加签名

if (success)
{
    Console.WriteLine("文件下载成功");
}
下载到内存

将文件下载到内存中进行处理:

// 创建进度回调
var progress = new Progress<double>(percent => 
{
    Console.WriteLine($"下载进度: {percent:P2}");
});

// 下载到字节数组
byte[] imageData = await client.Download.DownloadToByteArrayAsync(
    url: "http://example.com/my-bucket/images/photo.jpg",
    isPrivate: false,
    progress: progress);

// 使用下载的数据
using var memoryStream = new MemoryStream(imageData);
using var image = System.Drawing.Image.FromStream(memoryStream);
Console.WriteLine($"图片尺寸: {image.Width}x{image.Height}");

// 下载到流
using var fileStream = File.Create("C:\\Downloads\\document.docx");
await client.Download.DownloadToStreamAsync(
    url: "http://example.com/my-bucket/documents/document.docx",
    targetStream: fileStream,
    isPrivate: true,
    progress: progress);
断点续传下载

支持从指定位置开始下载:

// 获取已下载的部分大小
long existingFileSize = 0;
string filePath = "C:\\Downloads\\large-video.mp4";
if (File.Exists(filePath))
{
    existingFileSize = new FileInfo(filePath).Length;
}

// 从断点继续下载
using var fileStream = new FileStream(
    filePath, 
    FileMode.OpenOrCreate, 
    FileAccess.Write);

fileStream.Position = existingFileSize;

bool success = await client.Download.DownloadToStreamAsync(
    url: "http://example.com/my-bucket/videos/large-video.mp4",
    targetStream: fileStream,
    startPosition: existingFileSize);

CDN 管理

刷新缓存

当资源更新后,刷新CDN缓存:

// 刷新单个文件
var singleRefreshResult = await client.Cdn.RefreshUrlsAsync(
    new[] { "http://cdn.example.com/images/logo.png" });

// 批量刷新文件
var urls = new[] 
{ 
    "http://cdn.example.com/css/style.css", 
    "http://cdn.example.com/js/app.js",
    "http://cdn.example.com/images/banner.jpg" 
};

var refreshResult = await client.Cdn.RefreshUrlsAsync(urls);
Console.WriteLine($"刷新成功: {refreshResult.IsSuccess}, 刷新数量: {refreshResult.SuccessCount}");

// 刷新目录(递归刷新该目录下所有文件)
var dirs = new[] 
{ 
    "http://cdn.example.com/css/", 
    "http://cdn.example.com/js/" 
};

var refreshDirResult = await client.Cdn.RefreshDirsAsync(dirs);
Console.WriteLine($"目录刷新成功: {refreshDirResult.IsSuccess}, 刷新数量: {refreshDirResult.SuccessCount}");
预取资源

提前将资源缓存到CDN节点,加速用户访问:

// 预取单个文件
var singlePrefetchResult = await client.Cdn.PrefetchUrlsAsync(
    new[] { "http://cdn.example.com/videos/intro.mp4" });

// 批量预取文件
var urls = new[] 
{ 
    "http://cdn.example.com/videos/product1.mp4", 
    "http://cdn.example.com/videos/product2.mp4" 
};

var prefetchResult = await client.Cdn.PrefetchUrlsAsync(urls);
Console.WriteLine($"预取成功: {prefetchResult.IsSuccess}, 预取数量: {prefetchResult.SuccessCount}");
获取带宽和流量统计

查询CDN使用情况:

// 定义查询域名
var domains = new[] { "cdn.example.com" };

// 获取带宽数据(最近7天,按天统计)
var bandwidthData = await client.Cdn.GetBandwidthDataAsync(
    domains: domains, 
    startDate: DateTime.Now.AddDays(-7), 
    endDate: DateTime.Now, 
    granularity: "day");

// 输出带宽数据
foreach (var item in bandwidthData.Data)
{
    Console.WriteLine($"日期: {item.Time}, 带宽: {item.Bandwidth / 1024 / 1024:F2} Mbps");
}

// 获取流量数据(最近30天,按天统计)
var fluxData = await client.Cdn.GetFluxDataAsync(
    domains: domains, 
    startDate: DateTime.Now.AddDays(-30), 
    endDate: DateTime.Now, 
    granularity: "day");

// 输出流量数据
foreach (var item in fluxData.Data)
{
    Console.WriteLine($"日期: {item.Time}, 流量: {item.Flux / 1024 / 1024 / 1024:F2} GB");
}
获取CDN日志

下载CDN访问日志进行分析:

// 获取昨天的日志下载链接
var domains = new[] { "cdn.example.com" };
var logLinks = await client.Cdn.GetCdnLogsAsync(
    domains: domains, 
    date: DateTime.Today.AddDays(-1));

// 输出日志链接
foreach (var domain in logLinks.Data)
{
    Console.WriteLine($"域名: {domain.Domain}");
    foreach (var log in domain.Logs)
    {
        Console.WriteLine($"  日期: {log.Date}, 日志名: {log.Name}");
        Console.WriteLine($"  下载链接: {log.Url}");
        
        // 下载日志文件
        await client.Download.DownloadToFileAsync(
            url: log.Url,
            saveToPath: $"C:\\Logs\\{domain.Domain}_{log.Date}_{log.Name}");
    }
}

错误处理与异常管理

Sage.CloudStorage.Qiniu 提供了丰富的错误处理机制,帮助您更好地诊断和处理问题:

try
{
    // 尝试创建存储空间
    await client.Bucket.CreateBucketAsync("new-bucket", "z0");
}
catch (QiniuException ex) when (ex.Code == 401)
{
    // 处理认证错误
    Console.WriteLine("认证失败,请检查您的密钥是否正确");
    Console.WriteLine($"详细信息: {ex.Message}");
}
catch (QiniuException ex) when (ex.Code == 614)
{
    // 处理存储空间已存在的情况
    Console.WriteLine("存储空间已存在,无需重复创建");
}
catch (QiniuException ex)
{
    // 处理其他七牛云特定错误
    Console.WriteLine($"七牛云错误 - 代码: {ex.Code}, 信息: {ex.Message}");
    Console.WriteLine($"请求ID: {ex.RequestId}");
    Console.WriteLine($"响应详情: {ex.ResponseJson}");
    
    // 记录到日志系统
    _logger.LogError(ex, "七牛云操作失败");
}
catch (HttpRequestException ex)
{
    // 处理网络请求错误
    Console.WriteLine($"网络请求错误: {ex.Message}");
    if (ex.InnerException != null)
    {
        Console.WriteLine($"内部错误: {ex.InnerException.Message}");
    }
}
catch (Exception ex)
{
    // 处理其他未预期的错误
    Console.WriteLine($"未预期错误: {ex.Message}");
    Console.WriteLine($"堆栈跟踪: {ex.StackTrace}");
}
错误重试策略

对于网络不稳定的环境,可以实现重试策略:

public async Task<bool> UploadWithRetryAsync(string filePath, string key, int maxRetries = 3)
{
    int attempts = 0;
    while (attempts < maxRetries)
    {
        try
        {
            attempts++;
            Console.WriteLine($"尝试上传,第 {attempts} 次");
            
            // 执行上传操作
            var result = await client.Upload.UploadFileAsync(filePath, key);
            return result.IsSuccess;
        }
        catch (QiniuException ex) when (ex.IsTransientError() && attempts < maxRetries)
        {
            // 对于临时错误,等待后重试
            int delayMs = 1000 * attempts; // 递增延迟
            Console.WriteLine($"遇到临时错误,{delayMs/1000}秒后重试: {ex.Message}");
            await Task.Delay(delayMs);
        }
        catch (Exception ex)
        {
            // 对于非临时错误,立即失败
            Console.WriteLine($"上传失败: {ex.Message}");
            return false;
        }
    }
    
    Console.WriteLine($"达到最大重试次数 {maxRetries},上传失败");
    return false;
}

资源管理与释放

QiniuClient 实现了 IDisposable 接口,提供多种资源释放方式:

// 1. 使用 using 语句(推荐)
using (var client = new QiniuClient("access-key", "secret-key"))
{
    // 在此块中执行所有操作
    await client.Bucket.ListBucketsAsync();
    // 离开块时自动释放资源
}

// 2. 使用 using 声明(C# 8.0+)
using var longLivedClient = new QiniuClient("access-key", "secret-key");
// 在方法结束时自动释放资源

// 3. 手动释放(不推荐,除非有特殊需求)
var manualClient = new QiniuClient("access-key", "secret-key");
try
{
    // 执行操作
}
finally
{
    // 确保资源被释放
    manualClient.Dispose();
}

依赖注入集成

在 ASP.NET Core 或其他支持依赖注入的应用中,可以注册为服务:

// 在 Startup.cs 或 Program.cs 中
public void ConfigureServices(IServiceCollection services)
{
    // 注册HttpClient和HttpRequestManager
    services.AddHttpClient("QiniuHttpClient", client =>
    {
        // 配置HttpClient,例如设置超时、默认请求头等
        client.Timeout = TimeSpan.FromSeconds(60);
    });

    // 注册为单例服务
    services.AddSingleton<IQiniuClient>(provider =>
    {
        var configuration = provider.GetRequiredService<IConfiguration>();
        var accessKey = configuration["Qiniu:AccessKey"];
        var secretKey = configuration["Qiniu:SecretKey"];
        
        // 创建HttpRequestManager
        var httpManager = new HttpRequestManager(HttpClientSingleton.Instance);
        
        return new QiniuClient(accessKey, secretKey, httpManager, new QiniuConfig
        {
            UseHttps = true,
            AutoSelectUploadHost = true
        });
    });
    
    // 或注册为作用域服务(使用自定义HttpRequestManager)
    services.AddScoped<IQiniuClient>(provider =>
    {
        var configuration = provider.GetRequiredService<IConfiguration>();
        var accessKey = configuration["Qiniu:AccessKey"];
        var secretKey = configuration["Qiniu:SecretKey"];
        
        // 获取HttpClientFactory并创建自定义的HttpRequestManager
        var httpClientFactory = provider.GetRequiredService<IHttpClientFactory>();
        var httpClient = httpClientFactory.CreateClient("QiniuHttpClient");
        var loggerFactory = provider.GetRequiredService<ILoggerFactory>();
        var httpManager = new HttpRequestManager(httpClient, loggerFactory.CreateLogger<HttpRequestManager>());
        
        // 使用自定义HttpRequestManager创建QiniuClient
        return new QiniuClient(accessKey, secretKey, httpManager, new QiniuConfig
        {
            UseHttps = true,
            AutoSelectUploadHost = true
        });
    });
}

然后在控制器或服务中注入:

public class FileController : Controller
{
    private readonly IQiniuClient _qiniuClient;
    
    public FileController(IQiniuClient qiniuClient)
    {
        _qiniuClient = qiniuClient;
    }
    
    public async Task<IActionResult> Upload(IFormFile file)
    {
        if (file == null) return BadRequest("No file provided");
        
        using var stream = file.OpenReadStream();
        var result = await _qiniuClient.Upload.UploadStreamAsync(
            stream, 
            file.FileName, 
            "my-bucket");
            
        if (result.IsSuccess)
        {
            return Ok(new { url = result.FileUrl });
        }
        
        return StatusCode(500, result.ErrorMessage);
    }
}

最佳实践与注意事项

性能优化

  • 大文件处理:对于大于10MB的文件,始终使用分片上传
  • 并发控制:根据服务器资源调整并发上传数量,避免资源耗尽
  • CDN加速:对于频繁访问的资源,使用CDN预取功能提前缓存
  • 连接复用:长时间运行的应用应使用单例模式的客户端实例

安全建议

  • 密钥保护:永远不要在客户端代码中硬编码密钥,使用配置文件或环境变量
  • 上传策略:使用严格的上传策略限制文件大小、类型和存储位置
  • 私有资源:对敏感资源使用私有存储,并设置合理的链接有效期
  • 防盗链:为重要资源配置Referer防盗链和IP白名单

常见问题

  • 上传失败:检查网络连接、存储空间配额和文件大小限制
  • 授权错误:验证AccessKey和SecretKey是否正确,以及是否有对应权限
  • 域名绑定:确保自定义域名已正确CNAME到七牛云域名

许可证

本项目采用 Apache 2.0 许可证。详情请参阅 LICENSE 文件。

贡献

欢迎提交问题报告和改进建议。如果您想贡献代码,请提交拉取请求。

作者

  • LiuPengLai - 甲壳虫科技 欢迎提交问题和功能请求。 QQ Group: 1054304346
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0.3 163 8/28/2025
1.0.0.2 160 8/27/2025
1.0.0.1 162 8/27/2025
1.0.0 161 8/27/2025

修复客户端初始化时不能传递sage.http的对象问题