Javxp.Storage 1.0.2

dotnet add package Javxp.Storage --version 1.0.2
                    
NuGet\Install-Package Javxp.Storage -Version 1.0.2
                    
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="Javxp.Storage" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Javxp.Storage" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Javxp.Storage" />
                    
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 Javxp.Storage --version 1.0.2
                    
#r "nuget: Javxp.Storage, 1.0.2"
                    
#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 Javxp.Storage@1.0.2
                    
#: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=Javxp.Storage&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Javxp.Storage&version=1.0.2
                    
Install as a Cake Tool

Javxp.Storage

面向 .NET 10 的本地磁盘和阿里云 OSS 存储库。普通保存和 OSS 保存统一返回 Task<SaveResponse>;OSS Multipart 对外保留初始化、上传和取消三个操作。

安装与注册

dotnet add package Javxp.Storage
using Javxp.Storage;

builder.Services.JavxpStorage();

也可以直接实例化:

IStorageService storage = new StorageService();

运行环境为 .NET 10,主要依赖 Aliyun.OSS.SDK.NetCore 2.14.1 和 Microsoft.Extensions.DependencyInjection.Abstractions 10.0.12。

SaveResponse

public sealed class SaveResponse
{
    public bool Success { get; set; }
    public string Message { get; set; }
    public string FileName { get; set; }
}

Success 表示操作是否完成;Message 保存成功消息或错误信息;FileName 在本地操作中是完整文件路径,在 OSS 操作中是对象 URL。

本地保存

父目录会自动创建,目标文件默认覆盖。调用方传入的 Stream 不会由库关闭。

SaveResponse bytesResult = await storage.SaveAsync(bytes, @"D:\Storage\data.bin");

await using Stream input = File.OpenRead(@"D:\Input\archive.zip");
SaveResponse streamResult = await storage.SaveAsync(input, @"D:\Storage\archive.zip");

SaveResponse urlResult = await storage.SaveAsync(
    "https://example.com/files/photo.jpg",
    @"D:\Storage\photo.jpg");
Task<SaveResponse> SaveAsync(byte[] data, string filePath, CancellationToken cancellationToken = default);
Task<SaveResponse> SaveAsync(Stream stream, string filePath, CancellationToken cancellationToken = default);
Task<SaveResponse> SaveAsync(string url, string filePath, CancellationToken cancellationToken = default);

另外提供以下输入重载,它们会先转换为 byte[],再调用 byte[] 核心保存方法:

SaveAsync(FileInfo file, string filePath, ...);
SaveAsync(ReadOnlyMemory<byte> data, string filePath, ...);
SaveAsync(ReadOnlySequence<byte> data, string filePath, ...);
SaveAsync(HttpContent content, string filePath, ...);
SaveAsync(PipeReader reader, string filePath, ...);
SaveAsync(IAsyncEnumerable<ReadOnlyMemory<byte>> chunks, string filePath, ...);
SaveAsync(TextReader reader, string filePath, Encoding? encoding = null, ...);

OSS 同样提供这些输入类型的重载。文本输入默认使用 UTF-8,也可以显式传入其他 Encoding。

这些重载会把完整内容加载到内存。大文件不建议使用它们,应使用 Multipart 流式上传。

OSS 普通上传

AliyunOssOptions 只保存连接和 Bucket 信息;ObjectName 由每次上传调用单独传入,因此同一配置可以复用到多个对象。

var options = new AliyunOssOptions(
    endpoint: "oss-cn-shenzhen.aliyuncs.com",
    accessKeyId: accessKeyId,
    accessKeySecret: accessKeySecret,
    bucketName: "platform-yjlglobal-cn");

SaveResponse response = await storage.SaveAliyunOssAsync(
    bytes,
    options,
    objectName: $"{Guid.NewGuid():N}.pdf");

也可以使用对象初始化器:

var options = new AliyunOssOptions
{
    Endpoint = "oss-cn-shenzhen.aliyuncs.com",
    AccessKeyId = accessKeyId,
    AccessKeySecret = accessKeySecret,
    BucketName = "platform-yjlglobal-cn"
};

签名:

Task<SaveResponse> SaveAliyunOssAsync(byte[] data, AliyunOssOptions options, string objectName, CancellationToken cancellationToken = default);
Task<SaveResponse> SaveAliyunOssAsync(Stream stream, AliyunOssOptions options, string objectName, CancellationToken cancellationToken = default);
Task<SaveResponse> SaveAliyunOssAsync(string url, AliyunOssOptions options, string objectName, CancellationToken cancellationToken = default);

EndPoint 是 Endpoint 的兼容别名,Bucket 是 BucketName 的兼容别名。普通 OSS 上传使用 SDK 默认签名方式,不需要 region 参数,同名对象默认覆盖。

Multipart 上传

初始化

Multipart 的对象名在初始化时单独传入,并由 MultipartUploadConfig 保存上传状态:

MultipartUploadConfig config = await storage.MultipartUpload_InitiateAsync(
    options,
    objectName: "videos/large.mp4",
    region: "cn-shenzhen");

if (!config.Success)
{
    Console.WriteLine(config.Message);
    return;
}

一步完成上传

await using Stream file = File.OpenRead(@"D:\Input\large.mp4");
SaveResponse result = await storage.MultipartUploadAsync(file, config);

对于本地文件,也可以直接使用专用方法。它会以只读异步文件流打开文件,不会把整个文件一次性加载到内存:

SaveResponse result = await storage.MultipartUpload_LocalFileAsync(
    @"D:\Input\large.mp4",
    config,
    cancellationToken: cancellationToken);

本地文件上传会按 config.MaxConcurrency 并发上传分片,默认值为处理器数量的两倍;可以根据网络和 OSS 限流情况调整:

config.MaxConcurrency = 8;

每个分片都会独立打开本地文件并定位读取,上传过程会使用 OSS SDK 的传输进度事件持续报告进度。

MultipartUploadAsync 也支持 byte[] 和 URL 重载。内部会自动查询已有分片、上传剩余分片并完成合并。

暂停和恢复

MultipartUploadConfig.Stop 对应旧版 oss_v2.cs 的暂停标志。上传过程中由其他线程设置:

config.Stop = true;

当前分片完成后上传会返回暂停结果,并保留 UploadId 和已上传分片。恢复时使用同一个配置对象,将标志改回 false,再次调用同一个 MultipartUploadAsync:

config.Stop = false;
await using Stream resumedFile = File.OpenRead(@"D:\Input\large.mp4");
SaveResponse resumeResult = await storage.MultipartUploadAsync(resumedFile, config);

取消

SaveResponse abortResult = await storage.MultipartUpload_AbortAsync(config);

公开 Multipart 方法:

Task<MultipartUploadConfig> MultipartUpload_InitiateAsync(
    AliyunOssOptions options,
    string objectName,
    string region,
    int partSize = 5 * 1024 * 1024,
    CancellationToken cancellationToken = default);

Task<SaveResponse> MultipartUploadAsync(
    Stream stream,
    MultipartUploadConfig config,
    IProgress<MultipartUploadProgress>? progress = null,
    CancellationToken cancellationToken = default);

Task<SaveResponse> MultipartUpload_LocalFileAsync(
    string localFile,
    MultipartUploadConfig config,
    IProgress<MultipartUploadProgress>? progress = null,
    CancellationToken cancellationToken = default);

Task<SaveResponse> MultipartUpload_AbortAsync(
    MultipartUploadConfig config,
    CancellationToken cancellationToken = default);

默认分片大小为 5 MB,初始化时不能小于 100 KB,最后一个分片可以小于 100 KB。

安全说明

  • 不要把 AccessKeySecret 写入日志或提交到代码仓库。
  • AliyunOssOptions 不保存对象名,连接配置可以复用,但凭证仍应妥善保护。
  • AliyunOssOptions.ToString() 已脱敏。
  • 私有 Bucket 返回的 OSS URL 只表示对象位置,不保证匿名访问。

构建

dotnet build Javxp.Storage.csproj -c Release

当前 OSS SDK 的核心操作主要是同步 API,库内部使用异步包装执行;本地文件和 HTTP 下载使用原生异步 API。

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.2 86 9/21/2026
1.0.1 87 9/19/2026
1.0.0 117 6/4/2026