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

如何在Windows Form中实现多文件Azure存储上传的动态进度条(附示例)

Alright, let's tackle this multi-file upload to Azure File Share with a dynamic ProgressBar in Windows Forms. I've built similar workflows before, so here's a step-by-step breakdown with working code examples you can drop right into your project.

Multi-File Upload to Azure File Share with ProgressBar in Windows Forms

Prerequisites

  • First, install the Azure.Storage.Files.Shares NuGet package (this is the official, maintained SDK for Azure File Shares).
  • Set up your Windows Form with these controls:
    • A Button (to trigger file selection and upload)
    • An OpenFileDialog (configured to allow multiple file selection)
    • A ProgressBar (to show overall upload progress)
    • A Label (optional, to display which file is currently being uploaded)

Core Implementation

The main hurdles here are:

  1. Iterating through multiple files without freezing the UI (network/IO operations can't run on the main thread)
  2. Updating the ProgressBar correctly to reflect both individual file progress and overall batch progress

We'll use async/await for background processing and Control.Invoke to safely update UI elements from non-main threads.

Full Code Example

Here's the complete code for your Form (I'll assume your Form is named UploadForm):

using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AzureFileUploader
{
    public partial class UploadForm : Form
    {
        // Replace these with your actual Azure credentials and share details
        private const string AzureConnectionString = "your-azure-file-share-connection-string";
        private const string TargetShareName = "your-target-share-name";

        public UploadForm()
        {
            InitializeComponent();
            // Configure file picker to allow multiple selections
            openFileDialog1.Multiselect = true;
            // Set progress bar bounds
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;
        }

        private async void btnStartUpload_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() != DialogResult.OK)
                return;

            // Disable upload button to prevent duplicate clicks
            btnStartUpload.Enabled = false;
            progressBar1.Value = 0;
            lblStatus.Text = "Starting upload batch...";

            try
            {
                await UploadBatchToAzure(openFileDialog1.FileNames);
                MessageBox.Show("All files uploaded successfully!", "Upload Complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Upload failed: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                btnStartUpload.Enabled = true;
                lblStatus.Text = "Ready to upload";
            }
        }

        private async Task UploadBatchToAzure(string[] filePaths)
        {
            int totalFiles = filePaths.Length;
            int completedFiles = 0;

            // Initialize Azure File Share client
            ShareClient shareClient = new ShareClient(AzureConnectionString, TargetShareName);
            await shareClient.CreateIfNotExistsAsync();

            // Optional: Create a dedicated directory for uploads (remove if using root)
            ShareDirectoryClient uploadDir = shareClient.GetDirectoryClient("user-uploads");
            await uploadDir.CreateIfNotExistsAsync();

            foreach (string filePath in filePaths)
            {
                string fileName = Path.GetFileName(filePath);
                // Update status label to show current file
                Invoke((Action)(() => lblStatus.Text = $"Uploading: {fileName}"));

                ShareFileClient targetFile = uploadDir.GetFileClient(fileName);

                // Upload file with real-time progress tracking
                using (FileStream localFileStream = File.OpenRead(filePath))
                {
                    long totalFileSize = localFileStream.Length;
                    long bytesUploadedSoFar = 0;

                    await targetFile.UploadAsync(localFileStream, new ShareFileUploadOptions
                    {
                        ProgressHandler = new Progress<long>(bytesTransferred =>
                        {
                            bytesUploadedSoFar = bytesTransferred;
                            // Calculate overall progress: combine completed files + current file's progress
                            double overallProgress = (double)completedFiles / totalFiles * 100 + 
                                                     (double)bytesUploadedSoFar / totalFileSize / totalFiles * 100;
                            // Safely update progress bar on main thread
                            Invoke((Action)(() => progressBar1.Value = (int)Math.Round(overallProgress)));
                        })
                    });
                }

                completedFiles++;
                // Ensure progress bar reflects the completed file (in case progress handler didn't hit 100% exactly)
                double postFileProgress = (double)completedFiles / totalFiles * 100;
                Invoke((Action)(() => progressBar1.Value = (int)Math.Round(postFileProgress)));
            }
        }
    }
}

Key Details Explained

  • UI Responsiveness: We use async/await to run upload operations in the background, so the form doesn't freeze during file transfers. Never run network/IO code on the main UI thread!
  • Progress Calculation: The overall progress combines two parts:
    1. The percentage of files already fully uploaded (completedFiles / totalFiles * 100)
    2. The progress of the current file, scaled by the fraction of total files (so each file contributes equally to the overall bar)
  • Safe UI Updates: The progress handler runs on a background thread, so we use Control.Invoke to marshal UI updates back to the main thread—this avoids cross-thread UI exceptions.
  • Azure Setup: The code creates the target share and directory if they don't exist, so you don't need to pre-configure them in the Azure portal.

Important Production Notes

  • Security: Never hardcode your Azure connection string in the code. Store it in app.config or use Azure Key Vault for production applications.
  • Cancel Support: To add a cancel button, use a CancellationTokenSource and pass the token to the UploadAsync method.
  • Error Handling: The example has basic error handling, but you might want to add retries for transient Azure errors using libraries like Polly.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:11:54