MinIO (五) .net core实现分片上传

本文介绍了如何在Win11开发环境中,通过VS2022使用appsettings.json配置MinIO存储服务,包括配置参数和在API控制器中实现后端文件的分片上传功能。
摘要由CSDN通过智能技术生成

开发环境

Win11

vs2022

appsettings.json添加配置项

  //minIO配置
  "MinIO": {
    //服务器IP
    "Endpoint": "192.168.xx.xx:9090",
    //账号
    "AccessKey": "3xR7i4zs1vLnxxxxxxxx",
    //密码
    "SecretKey": "P6bAnyzJm47Ub4WsIaz3TB4MCxbF5Bk2xxxxxxxx",
    //默认存储桶
    "Bucket": "demo",
    //保存文件的根目录
    "BucketDirectory": "c:\\aaa\\bbb\\ccc",
    //服务的URL地址
    "ServiceURL": "http://192.168.xx.xx:9090" //不可以用localhost,要用IP,比服务器IP多了一个http前缀
  }

注入代码

[ApiController]
[Route("api/[controller]/[action]")]
//[Authorize]
public class MinIOController : ControllerBase
{
    private static string _bucketName = string.Empty;//默认桶
    private static string _accessKey = string.Empty;
    private static string _secretKey = string.Empty;
    private readonly MinioClient _client;
    private readonly IConfiguration _configuration;
    private readonly IHttpClientFactory _httpClient;

    public MinIOController(MinioClient client,
        IConfiguration configuration,
        IHttpClientFactory httpClient)
    {
        _client = client;
        _configuration = configuration;
        _accessKey = configuration["MinIO:AccessKey"];
        _secretKey = configuration["MinIO:SecretKey"];
        _bucketName = configuration["MinIO:Bucket"];
        _httpClient = httpClient;
    }
    
    //。。。。。。

}

接下来是后端进行分片上传的代码示例,有两个,第一个是从官方考下来的代码示例,第二个是自己整理后的代码示例。

从官方考下来的代码示例

#region 后端进行分片上传示例(从官方文档上考下来的)
/// <summary>
/// 后端进行分片上传示例(从官方文档上考下来的)
/// </summary>
/// <param name="formFile">文件流</param>
/// <returns></returns>
[HttpPost]
public virtual async Task<IActionResult> UploadPartAsync(IFormFile formFile)
{
    AmazonS3Config config = new AmazonS3Config()
    {
        ServiceURL = _configuration["MinIO:ServiceURL"]  //"http://192.168.50.36:9090/",
        //ServiceURL = "https://folder.s3.amazonaws.com/",
        //RegionEndpoint = Amazon.RegionEndpoint.CNNorth1
    };

    int MB = (int)Math.Pow(2, 20);  //以兆(M)为单位

    // Create a client
    using AmazonS3Client amazonS3Client = new AmazonS3Client(_configuration["MinIO:AccessKey"], _configuration["MinIO:SecretKey"], config);

    // Define input stream
    Stream inputStream = formFile.OpenReadStream(); //Create13MBDataStream();

    // Initiate multipart upload
    InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest
    {
        BucketName = "test",
        Key = "Item1"
    };
    //InitiateMultipartUploadResponse initResponse = client.InitiateMultipartUpload(initRequest);
    InitiateMultipartUploadResponse initResponse = await amazonS3Client.InitiateMultipartUploadAsync(initRequest);

    GetPreSignedUrlRequest urlRequest = new GetPreSignedUrlRequest()
    {
        BucketName = "test",
        Key = "Item1",
        PartNumber = 1,
        Expires = DateTime.Now.AddMinutes(1)
    };

    // Upload part 1
    UploadPartRequest uploadRequest = new UploadPartRequest
    {
        BucketName = "test",
        Key = "Item1",
        UploadId = initResponse.UploadId,
        PartNumber = 1,
        PartSize = 6 * MB,
        InputStream = inputStream
    };
    UploadPartResponse up1Response = await amazonS3Client.UploadPartAsync(uploadRequest);

    // Upload part 2
    uploadRequest = new UploadPartRequest
    {
        BucketName = "test",
        Key = "Item1",
        UploadId = initResponse.UploadId,
        PartNumber = 2,
        PartSize = 6 * MB,
        InputStream = inputStream
    };
    UploadPartResponse up2Response = await amazonS3Client.UploadPartAsync(uploadRequest);

    // Upload part 3
    uploadRequest = new UploadPartRequest
    {
        BucketName = "test",
        Key = "Item1",
        UploadId = initResponse.UploadId,
        PartNumber = 3,
        InputStream = inputStream
    };
    UploadPartResponse up3Response = await amazonS3Client.UploadPartAsync(uploadRequest);

    // List parts for current upload
    ListPartsRequest listPartRequest = new ListPartsRequest
    {
        BucketName = "test",
        Key = "Item1",
        UploadId = initResponse.UploadId
    };
    ListPartsResponse listPartResponse = await amazonS3Client.ListPartsAsync(listPartRequest);
    Debug.Assert(listPartResponse.Parts.Count == 3);

    // Complete the multipart upload  分片上传完后合并
    CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest
    {
        BucketName = "test",
        Key = "Item1",
        UploadId = initResponse.UploadId,
        PartETags = new List<PartETag>
        {
            new PartETag { ETag = up1Response.ETag, PartNumber = 1 },  //ETag就是分片信息
            new PartETag { ETag = up2Response.ETag, PartNumber = 2 },
            new PartETag { ETag = up3Response.ETag, PartNumber = 3 }
        }
    };
    CompleteMultipartUploadResponse compResponse = await amazonS3Client.CompleteMultipartUploadAsync(compRequest);

    return Ok();
}
#endregion 后端进行分片上传示例

整理后的后端进行分片上传

#region 后端进行分片上传示例
/// <summary>
/// 后端进行分片上传示例
/// </summary>
/// <param name="path">要上传的文件路径</param>
/// <param name="key">上传到MinIO的路径</param>
/// <returns></returns>
[HttpPost]
public virtual async Task<IActionResult> UploadPartTestAsync(string path, string key)
{
    try
    {
        AmazonS3Config config = new AmazonS3Config()
        {
            ServiceURL = _configuration["MinIO:ServiceURL"]  //"http://192.168.50.36:9090/",
            //ServiceURL = "https://folder.s3.amazonaws.com/",
            //RegionEndpoint = Amazon.RegionEndpoint.CNNorth1
        };

        int MB = (int)Math.Pow(2, 20);  //以兆(M)为单位(等同于1*1024*1024)
        List<PartETag> partETagList = new List<PartETag>();
        int partSize = 30 * MB;  //每片大小

        // Create a client
        using AmazonS3Client amazonS3Client = new AmazonS3Client(_configuration["MinIO:AccessKey"], _configuration["MinIO:SecretKey"], config);

        Stopwatch sw = new Stopwatch();
        sw.Start();
        //文件流
        //Stream inputStream = formFile.OpenReadStream(); //Create13MBDataStream();
        //var files = Request.Form.Files;
        using Stream inputStream = new FileStream(path, FileMode.OpenOrCreate);
        //await files[0].CopyToAsync(inputStream);

        // Initiate multipart upload
        InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest
        {
            BucketName = _configuration["MinIO:Bucket"],
            Key = key
        };
        //初始化分片上传,得到UploadId
        //InitiateMultipartUploadResponse initResponse = client.InitiateMultipartUpload(initRequest);
        InitiateMultipartUploadResponse initResponse = await amazonS3Client.InitiateMultipartUploadAsync(initRequest);
        TimeSpan ts = sw.Elapsed;
        sw.Restart();

        //得到URL
        //GetPreSignedUrlRequest urlRequest = new GetPreSignedUrlRequest()
        //{
        //    BucketName = _configuration["MinIO:Bucket"],
        //    Key = key,
        //    PartNumber = 1,
        //    Expires = DateTime.Now.AddMinutes(1)
        //};

        //分片数
        //int partCount = (int)Math.Ceiling((decimal)formFile.Length / partSize);
        int partCount = (int)Math.Ceiling((decimal)inputStream.Length / partSize);
        var tasks = new List<Task<UploadPartResponse>>();
        for (int i = 1; i <= partCount; i++)
        {
            UploadPartRequest uploadRequest = new UploadPartRequest();
            uploadRequest.BucketName = _configuration["MinIO:Bucket"];
            uploadRequest.Key = key;
            uploadRequest.UploadId = initResponse.UploadId;
            uploadRequest.PartNumber = i;
            uploadRequest.InputStream = inputStream;
            if (i != partCount)
            {
                uploadRequest.PartSize = partSize;
            }
            //进行分片上传
            UploadPartResponse up1Response = await amazonS3Client.UploadPartAsync(uploadRequest);
            //tasks.Add(Task.Run(async () => await amazonS3Client.UploadPartAsync(uploadRequest)));
            PartETag partETag = new PartETag { ETag = up1Response.ETag, PartNumber = i };
            partETagList.Add(partETag);
        }
        //UploadPartResponse[] resultArr = await Task.WhenAll(tasks.ToArray());
        //for (int i = 0; i < resultArr.Length; i++)
        //{
        //    PartETag partETag = new PartETag { ETag = resultArr[i].ETag, PartNumber = i };
        //    partETagList.Add(partETag);
        //}
        TimeSpan ts2 = sw.Elapsed;
        sw.Restart();

         List parts for current upload(列出当前上载的部件)
        //ListPartsRequest listPartRequest = new ListPartsRequest
        //{
        //    BucketName = _configuration["MinIO:Bucket"],
        //    Key = key,
        //    UploadId = initResponse.UploadId
        //};
        //ListPartsResponse listPartResponse = await amazonS3Client.ListPartsAsync(listPartRequest);
        //Debug.Assert(listPartResponse.Parts.Count == partCount);
        //TimeSpan ts3 = sw.Elapsed;
        //sw.Restart();

        // Complete the multipart upload  合并上传
        CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest
        {
            BucketName = _configuration["MinIO:Bucket"],
            Key = key,
            UploadId = initResponse.UploadId,
            PartETags = partETagList
        };
        CompleteMultipartUploadResponse compResponse = await amazonS3Client.CompleteMultipartUploadAsync(compRequest);
        TimeSpan ts4 = sw.Elapsed;
        sw.Restart();

        return Ok(new { Success = true, Message = "" });
    }
    catch (Exception ex)
    {
        return Ok(new { Success = true, Message = ex.Message });
    }
}
#endregion 后端进行分片上传示例

上一篇:abp vnext + MinIO(四)实现大文件上传

MinIO通过S3协议来实现分片上传和断点续传,具体步骤如下: 1. 初始化Multipart上传上传大文件之前,需要使用 `InitiateMultipartUpload` API 方法来初始化一个Multipart上传会话,并获取一个上传ID。上传ID用于标识一个Multipart上传会话。 ```python from minio import Minio from minio.error import ResponseError # 初始化MinIO客户端 minio_client = Minio( endpoint="minio.example.com", access_key="ACCESS_KEY", secret_key="SECRET_KEY", secure=False ) # 初始化Multipart上传会话 try: upload_id = minio_client.initiate_multipart_upload("my_bucket", "my_large_file").upload_id print("Upload ID:", upload_id) except ResponseError as err: print(err) ``` 2. 上传文件块 将大文件分成多个小块,每个小块的大小可以根据需求自定义。使用 `UploadPart` API 方法将每个小块独立上传上传时需要指定上传的文件名、块编号、块大小以及上传ID等信息。 ```python # 定义块大小(5MB) part_size = 5 * 1024 * 1024 # 上传文件块 try: # 打开待上传的文件 with open("my_large_file", "rb") as file_data: # 上传文件块 part_number = 1 parts = [] while True: # 读取文件块数据 part_data = file_data.read(part_size) if not part_data: break # 上传文件块 etag = minio_client.upload_part( "my_bucket", "my_large_file", part_number, upload_id, part_data).etag parts.append({"PartNumber": part_number, "ETag": etag}) part_number += 1 except ResponseError as err: print(err) ``` 3. 完成Multipart上传 上传所有文件块后,需要使用 `CompleteMultipartUpload` API 方法将它们合并成一个完整的文件,最终得到上传的文件。 ```python # 完成Multipart上传 try: minio_client.complete_multipart_upload( "my_bucket", "my_large_file", upload_id, parts) print("Upload complete!") except ResponseError as err: print(err) ``` 4. 断点续传 如果上传中断,可以使用 `ListParts` API 方法获取已上传的文件块信息,然后从中断处继续上传。 ```python # 断点续传 try: # 获取已上传的文件块信息 parts = minio_client.list_parts("my_bucket", "my_large_file", upload_id) # 继续上传文件块 for part in parts: if part.part_number < part_number: continue # 读取文件块数据 part_data = file_data.read(part_size) if not part_data: break # 上传文件块 etag = minio_client.upload_part( "my_bucket", "my_large_file", part_number, upload_id, part_data).etag parts.append({"PartNumber": part_number, "ETag": etag}) part_number += 1 # 完成Multipart上传 minio_client.complete_multipart_upload( "my_bucket", "my_large_file", upload_id, parts) print("Upload complete!") except ResponseError as err: print(err) ``` 以上是使用Python SDK实现MinIO文件服务器的分片上传和断点续传的基本步骤,具体实现还需要根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个程序员_zhangzhen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值