PHP Curl转.NET HttpRequest:多CSV文件带Token上传问题
Let's tackle this problem head-on. You're trying to convert a PHP cURL script for token-authenticated CSV uploads to C#, but ran into issues with WebClient's redirect loop and aren't sure if your RestClient implementation is correct. Here's how to fix everything:
First, let's confirm your token is being passed the same way as the PHP script. Assuming your PHP code looks like this (standard for token auth):
$ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer YOUR_TOKEN_HERE" ]); // ... rest of upload logic
Your C# code must mirror this header exactly. If the PHP script uses a custom header (e.g., X-Auth-Token), adjust your C# headers to match—this is critical for authentication to work.
The "Too many automatic redirections were attempted" error usually happens because:
- The server is sending a circular redirect (e.g., HTTP → HTTPS → HTTP repeatedly)
- WebClient's default redirect limit is hit (it's lower than you might expect)
Quick Fixes for WebClient:
- Disable auto-redirect and handle manually:
Then catchwebClient.AllowAutoRedirect = false;WebExceptionand check for 3xx status codes to follow the redirect URL manually. - Use the correct protocol: Double-check if your upload URL should use
https://instead ofhttp://—many servers force HTTPS and redirect repeatedly if you use HTTP. - Switch to HttpClient: WebClient is legacy; HttpClient has better redirect handling and is the recommended approach for .NET now.
Let's walk through the recommended HttpClient approach, plus a valid RestClient implementation, and a fixed WebClient version.
Recommended: HttpClient (.NET Core/.NET 5+)
This is the modern, maintainable way to handle HTTP requests in .NET:
using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; class CsvUploader { static async Task Main(string[] args) { var authToken = "YOUR_AUTH_TOKEN"; var uploadEndpoint = "https://your-server.com/upload"; // Reuse HttpClient (don't create a new instance every time!) using var httpClient = new HttpClient(); // Add token header to match PHP script httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken); // Build multipart form data (matches cURL's POSTFIELDS) using var formContent = new MultipartFormDataContent(); // Add single CSV file var firstCsvPath = @"C:\data\file1.csv"; var firstCsvBytes = await System.IO.File.ReadAllBytesAsync(firstCsvPath); var firstCsvContent = new ByteArrayContent(firstCsvBytes); firstCsvContent.Headers.ContentType = MediaTypeHeaderValue.Parse("text/csv"); formContent.Add(firstCsvContent, "files", "file1.csv"); // "files" = form field name (match PHP!) // Add multiple CSV files (reuse the same field name) var secondCsvPath = @"C:\data\file2.csv"; var secondCsvBytes = await System.IO.File.ReadAllBytesAsync(secondCsvPath); var secondCsvContent = new ByteArrayContent(secondCsvBytes); secondCsvContent.Headers.ContentType = MediaTypeHeaderValue.Parse("text/csv"); formContent.Add(secondCsvContent, "files", "file2.csv"); try { var response = await httpClient.PostAsync(uploadEndpoint, formContent); response.EnsureSuccessStatusCode(); // Throws if status code is 4xx/5xx var responseBody = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Upload succeeded! Response: {responseBody}"); } catch (HttpRequestException ex) { Console.WriteLine($"Upload failed: {ex.Message}"); } } }
Valid RestClient (RestSharp)
If you prefer RestSharp, make sure you're adding the token header and files correctly:
using RestSharp; using System; class RestSharpCsvUploader { static void Main(string[] args) { var authToken = "YOUR_AUTH_TOKEN"; var uploadEndpoint = "https://your-server.com/upload"; var client = new RestClient(uploadEndpoint); var request = new RestRequest(Method.POST); // Add token header (match PHP!) request.AddHeader("Authorization", $"Bearer {authToken}"); // Add single/multiple files request.AddFile("files", @"C:\data\file1.csv", "text/csv"); request.AddFile("files", @"C:\data\file2.csv", "text/csv"); try { var response = client.Execute(request); if (response.IsSuccessful) { Console.WriteLine($"Upload succeeded! Response: {response.Content}"); } else { Console.WriteLine($"Upload failed. Status: {response.StatusCode}, Error: {response.ErrorMessage}"); } } catch (Exception ex) { Console.WriteLine($"Upload failed: {ex.Message}"); } } }
Fixed WebClient Implementation
If you must use WebClient, here's how to handle multi-file uploads and fix redirects:
using System; using System.Net; using System.Text; class WebClientCsvUploader { static void Main(string[] args) { var authToken = "YOUR_AUTH_TOKEN"; var uploadEndpoint = "https://your-server.com/upload"; using var webClient = new WebClient(); // Add token header webClient.Headers.Add("Authorization", $"Bearer {authToken}"); // Fix redirect loop: disable auto-redirect (handle manually if needed) webClient.AllowAutoRedirect = false; try { var boundary = $"---------------------------{DateTime.Now.Ticks:x}"; webClient.Headers.Add("Content-Type", $"multipart/form-data; boundary={boundary}"); // Build multipart form data for multiple files var formBuilder = new StringBuilder(); var filePaths = new[] { @"C:\data\file1.csv", @"C:\data\file2.csv" }; foreach (var filePath in filePaths) { var fileName = System.IO.Path.GetFileName(filePath); formBuilder.AppendLine($"--{boundary}"); formBuilder.AppendLine($"Content-Disposition: form-data; name=\"files\"; filename=\"{fileName}\""); formBuilder.AppendLine("Content-Type: text/csv"); formBuilder.AppendLine(); formBuilder.AppendLine(System.IO.File.ReadAllText(filePath)); } formBuilder.AppendLine($"--{boundary}--"); var responseBytes = webClient.UploadData(uploadEndpoint, "POST", Encoding.UTF8.GetBytes(formBuilder.ToString())); var response = Encoding.UTF8.GetString(responseBytes); Console.WriteLine($"Upload succeeded! Response: {response}"); } catch (WebException ex) { Console.WriteLine($"Upload failed: {ex.Message}"); if (ex.Response is HttpWebResponse response) { Console.WriteLine($"Status Code: {response.StatusCode}"); // Handle redirect manually if needed if (response.StatusCode is HttpStatusCode.Redirect or HttpStatusCode.MovedPermanently) { var newUrl = response.Headers["Location"]; Console.WriteLine($"Redirecting to: {newUrl}"); // Repeat upload logic for newUrl here } } } } }
- Header Match: Confirm your C# token header is identical to the PHP script (e.g.,
Authorization: Bearer XYZvs custom headers likeX-Auth-Token). - Form Field Name: The field name used for files (e.g.,
"files") must match what the server expects—this is set in the PHPCURLFilekey. - Protocol: Use
https://if your server enforces it to avoid unnecessary redirects.
内容的提问来源于stack exchange,提问作者user5407401

