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

在ASP.NET Forms C#中异步传大文件至Azure Blob后删本地文件的最佳实践

Best Practices for Async Large File Uploads to Azure Blob Storage (ASP.NET Forms C#)

Hey Paul, great question—handling large file uploads asynchronously without making users wait is a super common scenario, and there are definitely polished best practices to make this implementation more reliable, maintainable, and resilient than a basic approach. Let’s break down the key improvements you can adopt:

1. Use Azure Blob’s Resumable, Chunked Uploads

Large files are prone to network interruptions, so leveraging Azure’s built-in chunked upload functionality is non-negotiable. The Azure.Storage.Blobs SDK automatically handles resumable transfers when you configure transfer options, splitting the file into manageable blocks and retrying failed chunks.

public async Task UploadFileToBlobAsync(ImageDetails objImageDetail, CancellationToken cancellationToken)
{
    var containerClient = new BlobContainerClient(yourConnectionString, "your-container-name");
    await containerClient.CreateIfNotExistsAsync(cancellationToken: cancellationToken);
    
    var blobClient = containerClient.GetBlobClient(objImageDetail.BlobName);
    
    // Configure chunked transfer settings (adjust based on your server/network capacity)
    var transferOptions = new StorageTransferOptions
    {
        MaximumConcurrency = 4, // Number of parallel chunk uploads
        MaximumTransferSize = 10 * 1024 * 1024, // 10MB per chunk (optimal for most scenarios)
        InitialTransferSize = 10 * 1024 * 1024
    };

    // Upload with resumable support
    await blobClient.UploadAsync(
        objImageDetail.LocalFilePath,
        overwrite: true,
        transferOptions: transferOptions,
        cancellationToken: cancellationToken);
}

2. Offload Uploads to a Background Service

ASP.NET Forms requests have timeouts, and AppPool recycles can kill long-running async tasks mid-execution. To avoid blocking users and ensure uploads complete reliably, offload the work to a background task system:

  • Hangfire: A simple, popular library for fire-and-forget background jobs in .NET apps.
  • ASP.NET Hosted Services: If your app targets .NET Core/.NET 5+, use built-in hosted services for long-running background tasks.
  • Azure Functions: Trigger an Azure Function to handle the upload (e.g., via a queue message when the file is saved locally).

Example with Hangfire:

// In your request handler (e.g., button click event)
protected async void UploadButton_Click(object sender, EventArgs e)
{
    // Save the uploaded file to a temporary local path first
    var tempPath = Path.Combine(Server.MapPath("~/TempUploads"), Guid.NewGuid().ToString());
    UploadedFile.SaveAs(tempPath);
    
    var imageDetail = new ImageDetails { LocalFilePath = tempPath, BlobName = "my-large-file.bin" };
    
    // Trigger background job and immediately return to the user
    BackgroundJob.Enqueue(() => UploadAndCleanupAsync(imageDetail));
    
    // Show success message to user right away
    StatusLabel.Text = "Upload started! We’ll handle the rest.";
}

// Background job method (should be public and parameterizable)
public async Task UploadAndCleanupAsync(ImageDetails objImageDetail)
{
    try
    {
        await UploadFileToBlobAsync(objImageDetail, CancellationToken.None);
        
        // Delete local file ONLY after successful upload
        if (File.Exists(objImageDetail.LocalFilePath))
        {
            File.Delete(objImageDetail.LocalFilePath);
        }
        
        // Log success (use a logging library like Serilog/NLog)
        Log.Information($"Successfully uploaded and cleaned up file: {objImageDetail.LocalFilePath}");
    }
    catch (Exception ex)
    {
        // Log failure details for debugging
        Log.Error(ex, $"Failed to upload file: {objImageDetail.LocalFilePath}");
        
        // Optional: Add retry logic for transient errors (see next point)
    }
}

3. Add Retry Logic for Transient Failures

Network blips and Azure service throttling can cause temporary upload failures. Use the Polly library to implement retry policies tailored to Azure’s common errors:

// Define a retry policy for Azure-specific transient errors
var retryPolicy = Policy
    .Handle<RequestFailedException>(ex => 
        ex.Status == (int)HttpStatusCode.RequestTimeout || 
        ex.ErrorCode == "OperationTimedOut" ||
        ex.ErrorCode == "ServerBusy")
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // Exponential backoff

// Use the policy around your upload call
await retryPolicy.ExecuteAsync(async () =>
{
    await blobClient.UploadAsync(
        objImageDetail.LocalFilePath,
        transferOptions: transferOptions,
        cancellationToken: cancellationToken);
});

4. Optimize Async/Await Usage to Avoid Deadlocks

In ASP.NET Forms, always use ConfigureAwait(false) when awaiting tasks that don’t need the request’s synchronization context (like blob uploads). This prevents potential deadlocks and improves performance:

await blobClient.UploadAsync(...).ConfigureAwait(false);
// ...
await File.DeleteAsync(objImageDetail.LocalFilePath).ConfigureAwait(false);

5. Validate and Clean Up Safely

  • Check file existence/permissions before attempting upload to avoid unnecessary exceptions.
  • Only delete local files after confirming successful upload: Never delete the file before the blob upload is fully completed and verified.
  • Handle cleanup failures: If deleting the local file fails (e.g., file is locked), log the issue and schedule a cleanup task later instead of failing the entire operation.

6. Bonus: Direct Browser-to-Blob Uploads (If Applicable)

If users are uploading files directly from a browser, skip your server entirely by generating a SAS token for Azure Blob Storage. This lets the browser upload files directly to Azure, reducing server load and eliminating the need to store temporary files locally. You’d generate the SAS token server-side, pass it to the frontend, and use JavaScript to handle the upload.


Key Takeaways

Your existing code might work for small files, but adding background processing, chunked uploads, retry logic, and robust logging will make it reliable for large files and production environments. Background tasks are especially critical to avoid blocking users and handling AppPool recycles gracefully.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:40:41