Simple WPF: S3實現MINIO大檔案上傳並顯示上傳進度

mrchip發表於2024-07-11

最新內容優先釋出於個人部落格:小虎技術分享站,隨後逐步搬運到部落格園。
創作不易,如果覺得有用請在Github上為博主點亮一顆小星星吧!

目的

早兩天寫了一篇S3簡單上傳檔案的小工具,知乎上看到了一個問題問如何實現顯示MINIO上傳進度,因此擴充一下這個小工具能夠在上傳大檔案時顯示進度。

完整程式碼託管於Github:mrchipset/simple-wpf

80XgKMHuN9beh6D86Zzup9KEG94t3qdNlx5aN_AuW-U.png

實現方式

  1. 先透過Xaml編寫一個包含上傳進度條的小介面。具體內容就不贅述了,可以參考這篇文章
  2. 為了得到上傳進度就不能再簡單地使用PutObjectRequest 進行上傳需要使用S3中TransferUtility 提供的高等級API進行上傳。
  3. 然後建立一個TransferUtilityUploadRequest 物件並繫結其UploadProgressEvent 事件以實現上傳進度的監控

具體的實現程式碼如下:

private async Task<bool> UploadLargeFileAsync()
{
    var credentials = new BasicAWSCredentials(_accessKey, _secretKey);

    var clientConfig = new AmazonS3Config
    {
        ForcePathStyle = true,
        ServiceURL = _endpoint,
    };

    bool ret = true;
    using (var client = new AmazonS3Client(credentials, clientConfig))
    {


        try
        {
            var fileTransferUtility = new TransferUtility(client);

            var uploadRequest = new TransferUtilityUploadRequest
            {
                BucketName = LargeBucket,
                FilePath = UploadLargeFile,
                Key = System.IO.Path.GetFileName(UploadLargeFile)
            };

            uploadRequest.UploadProgressEvent += UploadRequest_UploadProgressEvent;

            await fileTransferUtility.UploadAsync(uploadRequest);
        }
        catch (FileNotFoundException e)
        {
            ret = false;
            this.Dispatcher.Invoke(new Action(() => this.statusLargeTxtBlk.Text = e.Message));
        }
        catch (AmazonS3Exception e)
        {
            ret = false;
            if (e.ErrorCode != null &&
                (e.ErrorCode.Equals("InvalidAccessKeyId") ||
            e.ErrorCode.Equals("InvalidSecurity")))
            {
                this.Dispatcher.Invoke(new Action(() => this.statusLargeTxtBlk.Text = "Please check the provided AWS Credentials"));
            }
            else
            {
                this.Dispatcher.Invoke(new Action(() => this.statusLargeTxtBlk.Text = $"An error occurred with the message '{e.Message}' when writing an object"));
            }
        }
        catch(Exception e)
        {
            this.Dispatcher.Invoke(new Action(() => this.statusLargeTxtBlk.Text = $"An error occurred with the message '{e.Message}' when writing an object"));
        }
    }
    return ret;
}

private void UploadRequest_UploadProgressEvent(object? sender, UploadProgressArgs e)
{
    this.Dispatcher.Invoke((Action)(() =>
    {
        this.uploadProgress.Value = e.TransferredBytes * 100 / e.TotalBytes ;
    }));
}

值得一提的時,在上傳進度的事件處理函式中,由於我們透過非同步方法執行上傳函式,因此我們需要使用Dispatcher 來更新資料到UI 上。

演示效果

RrcNgGshrDzSeRmjcoMmk44kuWK1DLACH3xXRyIUKNw.gif

參考連線

https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-upload-object.html

https://www.xtigerkin.com/archives/96/

相關文章