使用MS Graph API发送大附件时遭遇WINHTTP_CALLBACK_STATUS_REQUEST_ERROR(12002)超时错误的求助
Hi there, sorry to hear you're hitting this timeout issue with large attachments in Microsoft Graph API. The WINHTTP_CALLBACK_STATUS_REQUEST_ERROR (12002) error typically happens when an upload request takes longer than the configured timeout limit to complete—this is super common with large files, where the default settings aren't sufficient. Let's go through actionable fixes to get this sorted:
1. Extend HttpClient Timeout
The default HttpClient used by GraphServiceClient has a relatively short timeout (usually around 100 seconds), which isn't enough for large file uploads. You need to explicitly set a longer timeout when initializing your client:
// Create a custom HttpClient with an extended timeout (adjust as needed for your file sizes) var httpClient = new HttpClient(); httpClient.Timeout = TimeSpan.FromMinutes(30); // 30 minutes gives plenty of time for large uploads // Initialize the credential and GraphServiceClient with the custom HttpClient var credential = new ClientSecretCredential(tenantId, clientId, secretVal); var myGPClient = new GraphServiceClient(credential, new[] { "https://graph.microsoft.com/.default" }, httpClient);
2. Optimize Upload Slice Size
Your current slice size (320 * 1024 * 9 = ~2.8MB) is valid (a multiple of 320KiB, required by Graph API) but on the smaller side. Smaller slices mean more individual requests, which increases the risk of timeouts. Try a larger, still valid slice size like 5MB (a common recommendation):
// Use a 5MB slice size (still a multiple of 320KiB) int maxSliceSize = 320 * 1024 * 16; // 5,242,880 bytes var fileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, fileStream, maxSliceSize);
3. Ensure File Stream Starts at Position 0
While opening a stream with FileMode.Open should default to position 0, it's safe to explicitly set it to avoid any accidental position shifts that could cause upload issues:
using (var fileStream = new FileStream(largeAttachment, FileMode.Open, FileAccess.Read)) { fileStream.Position = 0; // Guarantee the stream reads from the start of the file // Rest of your upload session setup code... }
4. Add Retry Logic for Transient Failures
Temporary network glitches can trigger timeouts. Using the Polly library to add retry logic for timeout errors and transient server issues will make your upload more robust:
First, install the required NuGet packages:
Install-Package Polly Install-Package Microsoft.Extensions.Http.Polly
Then configure your HttpClient with an exponential backoff retry policy:
// Define a retry policy for timeouts, network errors, and 5xx server responses var retryPolicy = Policy .Handle<HttpRequestException>() .Or<TimeoutException>() .OrResult<HttpResponseMessage>(r => r.StatusCode >= HttpStatusCode.InternalServerError) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // Exponential backoff to avoid overwhelming the server // Build HttpClient with retry policy and extended timeout var httpClient = HttpClientFactory.Create(client => { client.Timeout = TimeSpan.FromMinutes(30); }).AddPolicyHandler(retryPolicy); var credential = new ClientSecretCredential(tenantId, clientId, secretVal); var myGPClient = new GraphServiceClient(credential, new[] { "https://graph.microsoft.com/.default" }, httpClient);
5. Validate Attachment Metadata
Double-check two critical details:
- Ensure
GetMimeType(largeAttachment)returns the correct content type (e.g.,application/pdffor PDF files). An incorrect type can cause unexpected upload behavior. - Confirm
fileStream.Lengthmatches the actual size of your large file on disk. Mismatched sizes can lead to partial uploads or timeouts.
Once you implement these changes, the timeout error should be resolved, and your progress callback should start working as expected (since the upload will have enough time to process slices and trigger updates).
备注:内容来源于stack exchange,提问作者CDVS

