You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Forms中用Azure.Storage.Blobs V12实现分片上传与进度跟踪

Xamarin Forms + Azure.Storage.Blobs V12 分片上传与进度跟踪实现方案

一、分片上传实现(AzureDataLakeManager.cs 修改)

Azure Blob Storage V12 中,分片上传通过 BlockBlobClient 实现,核心流程是分块上传文件数据,最后提交块列表完成合并。以下是修改后的上传逻辑:

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Specialized;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

public class AzureDataLakeManager
{
    private readonly BlobServiceClient _blobServiceClient;
    private const int ChunkSize = 8 * 1024 * 1024; // 8MB 块大小,可根据需求调整(推荐4MB-100MB)

    public AzureDataLakeManager(string connectionString)
    {
        _blobServiceClient = new BlobServiceClient(connectionString);
    }

    /// <summary>
    /// 分片上传文件,并支持进度回调
    /// </summary>
    /// <param name="filePath">本地文件路径</param>
    /// <param name="containerName">ADLS容器名</param>
    /// <param name="blobName">目标Blob名称</param>
    /// <param name="progress">进度回调(已上传字节数)</param>
    /// <param name="cancellationToken">取消令牌</param>
    public async Task UploadFileInChunksAsync(string filePath, string containerName, string blobName, IProgress<long> progress, CancellationToken cancellationToken = default)
    {
        var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
        await containerClient.CreateIfNotExistsAsync(cancellationToken: cancellationToken);

        var blockBlobClient = containerClient.GetBlockBlobClient(blobName);
        var blockIds = new List<string>();
        long totalBytesUploaded = 0;

        using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = new byte[ChunkSize];
            int bytesRead;
            int blockIndex = 0;

            while ((bytesRead = await fileStream.ReadAsync(buffer, 0, ChunkSize, cancellationToken)) > 0)
            {
                // 生成唯一块ID(必须Base64编码)
                string blockId = System.Convert.ToBase64String(System.BitConverter.GetBytes(blockIndex));
                blockIds.Add(blockId);

                // 上传当前块
                using (var chunkStream = new MemoryStream(buffer, 0, bytesRead))
                {
                    await blockBlobClient.StageBlockAsync(blockId, chunkStream, cancellationToken: cancellationToken);
                }

                // 更新已上传字节数并触发进度回调
                totalBytesUploaded += bytesRead;
                progress?.Report(totalBytesUploaded);

                blockIndex++;
                cancellationToken.ThrowIfCancellationRequested();
            }

            // 提交所有块,完成文件合并
            await blockBlobClient.CommitBlockListAsync(blockIds, cancellationToken: cancellationToken);
        }
    }
}

二、进度跟踪与ProgressBar联动(MyStudio.Xaml + MyStudio.Xaml.cs)

1. XAML布局(MyStudio.Xaml)

确保布局中包含ProgressBar及相关控件:

<StackLayout Margin="20">
    <Button x:Name="UploadBtn" Text="开始上传" Clicked="UploadBtn_Clicked"/>
    <ProgressBar x:Name="UploadProgressBar" Progress="0" HeightRequest="20" Margin="0,10,0,0"/>
    <Label x:Name="ProgressLabel" Text="0%" Margin="0,5,0,0"/>
</StackLayout>

2. 代码逻辑(MyStudio.Xaml.cs)

通过 IProgress<long> 接收上传进度,在UI线程更新ProgressBar和进度文本:

using Xamarin.Forms;
using System;
using System.IO;

public partial class MyStudio : ContentPage
{
    private readonly AzureDataLakeManager _adlsManager;
    private long _totalFileSize; // 上传文件总大小

    public MyStudio()
    {
        InitializeComponent();
        // 替换为你的ADLS连接字符串
        _adlsManager = new AzureDataLakeManager("your-adls-connection-string");
    }

    private async void UploadBtn_Clicked(object sender, EventArgs e)
    {
        UploadBtn.IsEnabled = false;
        UploadProgressBar.Progress = 0;
        ProgressLabel.Text = "0%";

        // 替换为你的本地文件路径、容器名、Blob名
        string filePath = "/path/to/your/local/file";
        string containerName = "your-container";
        string blobName = "target-file-name.ext";

        // 获取文件总大小
        var fileInfo = new FileInfo(filePath);
        _totalFileSize = fileInfo.Length;

        // 定义进度回调,确保在UI线程更新控件
        var progress = new Progress<long>(bytesUploaded =>
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                double progressValue = (double)bytesUploaded / _totalFileSize;
                UploadProgressBar.Progress = progressValue;
                ProgressLabel.Text = $"{Math.Round(progressValue * 100)}%";
            });
        });

        try
        {
            await _adlsManager.UploadFileInChunksAsync(filePath, containerName, blobName, progress);
            await DisplayAlert("成功", "文件上传完成", "确定");
        }
        catch (Exception ex)
        {
            await DisplayAlert("错误", $"上传失败:{ex.Message}", "确定");
        }
        finally
        {
            UploadBtn.IsEnabled = true;
        }
    }
}

关键注意事项

  • 块大小:推荐设置为4MB到100MB之间,过小会增加API调用次数,过大可能导致单块上传超时。
  • 块ID:必须是Base64编码的唯一值,且长度不能超过64字节。
  • UI线程更新:Xamarin Forms中所有UI操作必须在主线程执行,因此用 Device.BeginInvokeOnMainThread 包裹进度更新逻辑。
  • 异常处理:可根据需求添加块上传重试逻辑,避免网络波动导致的上传失败。

内容的提问来源于stack exchange,提问作者hk77

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:28:22