如何在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.
Prerequisites
- First, install the
Azure.Storage.Files.SharesNuGet 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)
- A
Core Implementation
The main hurdles here are:
- Iterating through multiple files without freezing the UI (network/IO operations can't run on the main thread)
- 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/awaitto 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:
- The percentage of files already fully uploaded (
completedFiles / totalFiles * 100) - The progress of the current file, scaled by the fraction of total files (so each file contributes equally to the overall bar)
- The percentage of files already fully uploaded (
- Safe UI Updates: The progress handler runs on a background thread, so we use
Control.Invoketo 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.configor use Azure Key Vault for production applications. - Cancel Support: To add a cancel button, use a
CancellationTokenSourceand pass the token to theUploadAsyncmethod. - 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
相关产品推荐
相关产品推荐

