不要使用 - 使用[apache-commons-httpclient],[apache-httpclient-4.x],[java-http-client],[dotnet-httpclient]或[angular-httpclient]
我有一个运行状态的 .php 脚本,它点击 URL 并上传单个/多个文件 .csv 类型,并带有随它们一起发送的唯一令牌(据我所知在正文中)。以下是工作片段: PHP 我有一个运行状态 .php 脚本,可以点击 URL 并上传单个/多个文件 .csv 类型,并随其发送唯一的 token(据我所知在正文中)。以下是工作片段: PHP <?php error_reporting(E_ALL); ini_set('display_errors', 1); $ch = curl_init('http://demo.schooling.net/school/attendance'); $DirPath = "E:/Uploads/"; $ZKFiles=array(); if ($dh = opendir($DirPath)) { while (($file = readdir($dh)) !== false) { if ($file == '.' || $file == '..') { continue; } $ZKFiles[]='@'.$DirPath.$file; } closedir($dh); } if(!empty($ZKFiles)) { // Assign POST data curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch,CURLOPT_FAILONERROR,false); curl_setopt_custom_postfields($ch, array('Files[]'=>$ZKFiles,'token'=>'fe60313b0edfdfaf757f9744815454545')); // Execute the handle $execResult=curl_exec($ch); if($execResult=== false) { echo 'Curl error: ' . curl_error($ch); } else { echo 'Operation completed without any errors'; echo $execResult; } } function curl_setopt_custom_postfields($ch, $postfields, $headers = null) { $algos = hash_algos(); $hashAlgo = null; foreach ( array('sha1', 'md5') as $preferred ) { if ( in_array($preferred, $algos) ) { $hashAlgo = $preferred; break; } } if ( $hashAlgo === null ) { list($hashAlgo) = $algos; } $boundary = '----------------------------' . substr(hash($hashAlgo, 'cURL-php-multiple-value-same-key-support' . microtime()), 0, 12); $body = array(); $crlf = "\r\n"; $fields = array(); foreach ( $postfields as $key => $value ) { if ( is_array($value) ) { foreach ( $value as $v ) { $fields[] = array($key, $v); } } else { $fields[] = array($key, $value); } } //print_r($fields);die(); foreach ( $fields as $field ) { list($key, $value) = $field; if ( strpos($value, '@') === 0 ) { preg_match('/^@(.*?)$/', $value, $matches); list($dummy, $filename) = $matches; $body[] = '--' . $boundary; $body[] = 'Content-Disposition: form-data; name="' . $key . '"; filename="' . basename($filename) . '"'; $body[] = 'Content-Type: application/octet-stream'; $body[] = ''; $body[] = file_get_contents($filename); } else { $body[] = '--' . $boundary; $body[] = 'Content-Disposition: form-data; name="' . $key . '"'; $body[] = ''; $body[] = $value; } } $body[] = '--' . $boundary . '--'; $body[] = ''; //print_r($body);die(); $contentType = 'multipart/form-data; boundary=' . $boundary; $content = join($crlf, $body); $contentLength = strlen($content); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Length: ' . $contentLength, 'Expect: 100-continue', 'Content-Type: ' . $contentType, )); //echo $content;die(); curl_setopt($ch, CURLOPT_POSTFIELDS, $content); } ?> 为了在 .NET 中实现这一目标,到目前为止我已经尝试过(所有可能的方法) 第一次尝试 - 使用 WebClient: [HttpPost] public void SendFiles() { string fileToUpload = @"E:\Uploads\demo.csv"; string url ="http://demo.schooling.net/school/attendance"; using (var client = new WebClient()) { //sending token and then uplaoding file System.Collections.Specialized.NameValueCollection postData = new System.Collections.Specialized.NameValueCollection() { { "token", "fe60313b0edfdfaf757f9744815454545" } }; string pagesource = Encoding.UTF8.GetString(client.UploadValues(url, "POST", postData)); //string authInfo = Convert.ToBase64String(Encoding.Default.GetBytes("fe60313b0edfdfaf757f9744815454545")); client.Headers["token"] = "fe60313b0edfdfaf757f9744815454545"; client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"); byte[] result = client.UploadFile(url, fileToUpload); string responseAsString = Encoding.Default.GetString(result); } } 这不会将令牌发送到网址,因此页面会重定向到登录页面。 第二次尝试 - 使用 .NET MultipartDataContent: string fileUpload = @"E:\Uploads\demo.csv"; string uri = "http://demo.schooling.net/school/attendance"; //Using built-in MultipartFormDataContent HttpClient httpClient = new HttpClient(); MultipartFormDataContent form1 = new MultipartFormDataContent(); FileStream fs = System.IO.File.OpenRead(fileUpload); var streamContent = new StreamContent(fs); var Content = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result); Content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data"); //Add token here first form1.Add(new StringContent("fe60313b0edfdfaf757f9744815454545"), "token"); form1.Add(Content, "csv", Path.GetFileName(fileUpload)); var response = httpClient.PostAsync(uri, form1).Result; 这次失败了(没有发送令牌),因此我进行了第三次尝试。 第三次尝试 - 使用 MultipartForm 描述的 here: //Using Custom MultipartForm MultipartForm form = new MultipartForm(url); form.SetField("token", "fe60313b0edfdfaf757f9744815454545"); form.SendFile(@"E:\Uploads\demo.csv"); MultiPartForm.cs: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Collections; using System.Net; namespace Helpers { /// <summary> /// Allow the transfer of data files using the W3C's specification /// for HTTP multipart form data. Microsoft's version has a bug /// where it does not format the ending boundary correctly. /// Original version written by Gregory Prentice : [email protected] /// See: http://www.c-sharpcorner.com/UploadFile/gregoryprentice/DotNetBugs12062005230632PM/DotNetBugs.aspx /// </summary> public class MultipartForm { /// <summary> /// Holds any form fields and values that you /// wish to transfer with your data. /// </summary> private Hashtable coFormFields; /// <summary> /// Used mainly to avoid passing parameters to other routines. /// Could have been local to sendFile(). /// </summary> protected HttpWebRequest coRequest; /// <summary> /// Used if we are testing and want to output the raw /// request, minus http headers, out to a file. /// </summary> private Stream coFileStream; /// <summary> /// Defined to build the form field data that is being /// passed along with the request. /// </summary> private static string CONTENT_DISP = "Content-Disposition: form-data; name="; /// <summary> /// Allows you to specify the specific version of HTTP to use for uploads. /// The dot NET stuff currently does not allow you to remove the continue-100 header /// from 1.1 and 1.0 currently has a bug in it where it adds the continue-100. MS /// has sent a patch to remove the continue-100 in HTTP 1.0. /// </summary> public Version TransferHttpVersion { get; set; } /// <summary> /// Used to change the content type of the file being sent. /// Currently defaults to: text/xml. Other options are /// text/plain or binary /// </summary> public string FileContentType { get; set; } /// <summary> /// Initialize our class for use to send data files. /// </summary> /// <param name="url">The web address of the recipient of the data transfer.</param> public MultipartForm(string url) { URL = url; coFormFields = new Hashtable(); ResponseText = new StringBuilder(); BufferSize = 1024 * 10; BeginBoundary = "ou812--------------8c405ee4e38917c"; TransferHttpVersion = HttpVersion.Version11; //FileContentType = "text/xml"; FileContentType = "text/csv"; } //---------- BEGIN PROPERTIES SECTION ---------- private string _BeginBoundary; /// <summary> /// The string that defines the begining boundary of /// our multipart transfer as defined in the w3c specs. /// This method also sets the Content and Ending /// boundaries as defined by the w3c specs. /// </summary> public string BeginBoundary { get { return _BeginBoundary; } set { _BeginBoundary = value; ContentBoundary = "--" + BeginBoundary; EndingBoundary = ContentBoundary + "--"; } } /// <summary> /// The string that defines the content boundary of /// our multipart transfer as defined in the w3c specs. /// </summary> protected string ContentBoundary { get; set; } /// <summary> /// The string that defines the ending boundary of /// our multipart transfer as defined in the w3c specs. /// </summary> protected string EndingBoundary { get; set; } /// <summary> /// The data returned to us after the transfer is completed. /// </summary> public StringBuilder ResponseText { get; set; } /// <summary> /// The web address of the recipient of the transfer. /// </summary> public string URL { get; set; } /// <summary> /// Allows us to determine the size of the buffer used /// to send a piece of the file at a time out the IO /// stream. Defaults to 1024 * 10. /// </summary> public int BufferSize { get; set; } //---------- END PROPERTIES SECTION ---------- /// <summary> /// Used to signal we want the output to go to a /// text file verses being transfered to a URL. /// </summary> /// <param name="path"></param> public void SetFilename(string path) { coFileStream = new System.IO.FileStream(path, FileMode.Create, FileAccess.Write); } /// <summary> /// Allows you to add some additional field data to be /// sent along with the transfer. This is usually used /// for things like userid and password to validate the /// transfer. /// </summary> /// <param name="key">The form field name</param> /// <param name="str">The form field value</param> public void SetField(string key, string str) { coFormFields[key] = str; } /// <summary> /// Determines if we have a file stream set, and returns either /// the HttpWebRequest stream of the file. /// </summary> /// <returns></returns> public virtual Stream GetStream() { Stream stream; if (null == coFileStream) stream = coRequest.GetRequestStream(); else stream = coFileStream; return stream; } /// <summary> /// Here we actually make the request to the web server and /// retrieve it's response into a text buffer. /// </summary> public virtual void GetResponse() { if (null == coFileStream) { Stream stream; WebResponse response; try { response = coRequest.GetResponse(); } catch (WebException web) { response = web.Response; } if (null != response) { stream = response.GetResponseStream(); StreamReader sr = new StreamReader(stream); string str; ResponseText.Length = 0; while ((str = sr.ReadLine()) != null) ResponseText.Append(str); response.Close(); } else throw new Exception("MultipartForm: Error retrieving server response"); } } /// <summary> /// Transmits a file to the web server stated in the /// URL property. You may call this several times and it /// will use the values previously set for fields and URL. /// </summary> /// <param name="filename">The full path of file being transfered.</param> public void SendFile(string filename) { // The live of this object is only good during // this function. Used mainly to avoid passing // around parameters to other functions. coRequest = (HttpWebRequest)WebRequest.Create(URL); // Set use HTTP 1.0 or 1.1. coRequest.ProtocolVersion = TransferHttpVersion; coRequest.Method = "POST"; coRequest.ContentType = "multipart/form-data; boundary=" + BeginBoundary; coRequest.Headers.Add("Cache-Control", "no-cache"); coRequest.KeepAlive = true; string strFields = GetFormfields(); string strFileHdr = GetFileheader(filename); string strFileTlr = GetFiletrailer(); FileInfo info = new FileInfo(filename); coRequest.ContentLength = strFields.Length + strFileHdr.Length + strFileTlr.Length + info.Length; System.IO.Stream io; io = GetStream(); WriteString(io, strFields); WriteString(io, strFileHdr); this.WriteFile(io, filename); WriteString(io, strFileTlr); GetResponse(); io.Close(); // End the life time of this request object. coRequest = null; } /// <summary> /// Mainly used to turn the string into a byte buffer and then /// write it to our IO stream. /// </summary> /// <param name="stream">The io stream for output.</param> /// <param name="str">The data to write.</param> public void WriteString(Stream stream, string str) { byte[] postData = System.Text.Encoding.ASCII.GetBytes(str); stream.Write(postData, 0, postData.Length); } /// <summary> /// Builds the proper format of the multipart data that /// contains the form fields and their respective values. /// </summary> /// <returns>The data to send in the multipart upload.</returns> public string GetFormfields() { string str = ""; IDictionaryEnumerator myEnumerator = coFormFields.GetEnumerator(); while (myEnumerator.MoveNext()) { str += ContentBoundary + "\r\n" + CONTENT_DISP + '"' + myEnumerator.Key + "\"\r\n\r\n" + myEnumerator.Value + "\r\n"; } return str; } /// <summary> /// Returns the proper content information for the /// file we are sending. /// </summary> /// <remarks> /// Hits Patel reported a bug when used with ActiveFile. /// Added semicolon after sendfile to resolve that issue. /// Tested for compatibility with IIS 5.0 and Java. /// </remarks> /// <param name="filename"></param> /// <returns></returns> public string GetFileheader(string filename) { return ContentBoundary + "\r\n" + CONTENT_DISP + "\"sendfile\"; filename=\"" + Path.GetFileName(filename) + "\"\r\n" + "Content-type: " + FileContentType + "\r\n\r\n"; } /// <summary> /// Creates the proper ending boundary for the multipart upload. /// </summary> /// <returns>The ending boundary.</returns> public string GetFiletrailer() { return "\r\n" + EndingBoundary; } /// <summary> /// Reads in the file a chunk at a time then sends it to the /// output stream. /// </summary> /// <param name="stream">The io stream to write the file to.</param> /// <param name="filename">The name of the file to transfer.</param> public void WriteFile(Stream stream, string filename) { using (FileStream readIn = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { readIn.Seek(0, SeekOrigin.Begin); // move to the start of the file byte[] fileData = new byte[BufferSize]; int bytes; while ((bytes = readIn.Read(fileData, 0, BufferSize)) > 0) { // read the file data and send a chunk at a time stream.Write(fileData, 0, bytes); } } } } } 虽然没有运气,但有很大的宽容,第四次尝试到来了(这种方法也没有发送令牌) 第四次尝试 - 使用 HttpClient: using (var client = new HttpClient()) { using (var multipartFormDataContent = new MultipartFormDataContent()) { var values = new[] { new KeyValuePair<string, string>("token", "fe60313b0edfdfaf757f9744815454545") //other values }; foreach (var keyValuePair in values) { multipartFormDataContent.Add(new StringContent(keyValuePair.Value), String.Format("\"{0}\"", keyValuePair.Key)); } multipartFormDataContent.Add(new ByteArrayContent(System.IO.File.ReadAllBytes(@"E:\\Uploads\\demo.csv")), '"' + "File" + '"', '"' + "democollege.csv" + '"'); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", "fe60313b0edfdfaf757f9744815454545"); var requestUri = "http://demo.schooling.net/school/attendance"; var result = client.PostAsync(requestUri, multipartFormDataContent).Result; } } 这也让我失望了,同样没有令牌,最终没有上传文件 第五次尝试 - 使用 HttpWebRequest: public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) { string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.KeepAlive = true; wr.AllowAutoRedirect = false; // wr.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Your Oauth token"); wr.Headers.Add("Authorization", "Basic " + "fe60313b0edfdfaf757f9744815454545"); wr.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream rs = wr.GetRequestStream(); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (string key in nvc.Keys) { rs.Write(boundarybytes, 0, boundarybytes.Length); string formitem = string.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); rs.Write(formitembytes, 0, formitembytes.Length); } rs.Write(boundarybytes, 0, boundarybytes.Length); string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; string header = string.Format(headerTemplate, paramName, file, contentType); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[4096]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { rs.Write(buffer, 0, bytesRead); } fileStream.Close(); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); rs.Write(trailer, 0, trailer.Length); rs.Close(); WebResponse wresp = null; try { wresp = wr.GetResponse(); Stream stream2 = wresp.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); var result = reader2.ReadToEnd(); } catch (Exception ex) { // System.Windows.MessageBox.Show("Error occurred while converting file", "Error!"); if (wresp != null) { wresp.Close(); wresp = null; } } finally { wr = null; } } 然后调用该方法: string fileToUpload = @"E:\Uploads\demo.csv"; string url = "http://demo.schooling.net/school/attendance"; NameValueCollection nvc = new NameValueCollection(); nvc.Add("token", "fe60313b0edfdfaf757f9744815454545"); HttpUploadFile(url, fileToUpload, "file", "text/csv", nvc); 即使我正在获取表单数据(附加屏幕截图,使用上述尝试之一),这也失败了 通过在 PHP 脚本中添加此行: ...$body[] = ''; print_r($body);die(); 我可以在浏览器中看到这个: Array ( [0] => Array ( [0] => Files[] [1] => @E:/Uploads/demo.csv ) [1] => Array ( [0] => token [1] => fe60313b0edfdfaf757f9744815454545) ) 在 php 脚本中添加以下行: print_r($body); die(); 在 function curl_setopt_custom_postfields($ch, $postfields, $headers = null); 函数的末尾,我可以在浏览器上看到这个: Array ( [0] => ------------------------------3c935d382987 [1] => Content-Disposition: form-data; name="Files[]"; filename="demo.csv" [2] => Content-Type: application/octet-stream [3] => [4] => No,Name,Time,Verify,Mach,Ex,checktype,sid,code,Date 22364,22364,12/8/2017 10:28,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22365,22365,12/8/2017 9:29,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22366,22366,12/8/2017 10:59,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22369,22369,12/8/2017 11:58,Fingerpint,democollege-1-1,,I,1,0,12/8/2017 22364,22364,11/7/2017 10:28,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 22365,22365,11/7/2017 9:29,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 22366,22366,11/7/2018 10:59,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 22369,22369,11/7/2018 11:58,Fingerpint,democollege-1-1,,I,1,0,11/7/2017 [5] => ------------------------------3c935d382987 [6] => Content-Disposition: form-data; name="token" [7] => [8] => fe60313b0edfdfaf757f9744815454545 [9] => ------------------------------3c935d382987-- [10] => ) 提琴手: .Net Web Api 文件;上传、下载、图片审核和SendCloud服务 Web.config <appSettings> <!--FileService--> <add key="ftpUserName" value="fooUserName" /> <add key="ftpPassword" value="fooPass" /> <!--FileController--> <add key="fileServiceLocalPath" value="~/App_Data/Upload" /> <add key="fileServiceStoragePath" value="fooFtpAddress" /> <add key="useCloud" value="false" /> </appSettings> 具有身份验证的文件控制器 [Authorize] [RoutePrefix("api/File")] public class FileController : ApiController { IFileService fileService = null; public FileController(IFileService _fileService) { fileService = _fileService; } [Route("Upload"), HttpPost] public async Task<IHttpActionResult> Upload() { #region Condition if (!Request.Content.IsMimeMultipartContent()) return Content(HttpStatusCode.UnsupportedMediaType, Messages.FUW0001); #endregion /// `localPath` and `useCloud` is get from Web.Config. string localPath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileServiceLocalPath"]); bool useCloud = Convert.ToBoolean(ConfigurationManager.AppSettings["useCloud"]); var provider = new MultipartFormDataStreamProvider(localPath); try { /// Loads the files into the local storage. await Request.Content.ReadAsMultipartAsync(provider); /// Check is exist valid file. if (provider.FileData.Count == 0) return BadRequest(Messages.FUE0001 /*Message Type FUE001 = File Not Found */); IList<FileDto> modelList = new List<FileDto>(); foreach (MultipartFileData file in provider.FileData) { string originalName = file.Headers.ContentDisposition.FileName; if (originalName.StartsWith("\"") && originalName.EndsWith("\"")) { originalName = originalName.Trim('"'); } if (originalName.Contains(@"/") || originalName.Contains(@"\")) { originalName = Path.GetFileName(originalName); } /// File information storage my database. FileDto fileDto = new FileDto { OriginalName = Path.GetFileNameWithoutExtension(originalName), StorageName = Path.GetFileName(file.LocalFileName), Extension = Path.GetExtension(originalName).ToLower().Replace(".", ""), Size = new FileInfo(file.LocalFileName).Length }; modelList.Add(fileDto); } if (useCloud) await fileService.SendCloud(modelList,localPath); await fileService.Add(modelList, IdentityClaimsValues.UserID<Guid>()); return Ok(Messages.Ok); } catch (Exception exMessage) { return Content(HttpStatusCode.InternalServerError, exMessage); } } [ Route("Download"), HttpGet] public async Task<IHttpActionResult> Download(Guid id) { /// Get file information my database var model = await fileService.GetByID(id); if (model == null) return BadRequest(); /// `localPath` is get from Web.Config. string localPath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileServiceLocalPath"]); string root = localPath + "\\" + model.StorageName; byte[] fileData = File.ReadAllBytes(root); var stream = new MemoryStream(fileData, 0, fileData.Length); var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(stream.ToArray()) }; response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = model.OriginalName + "." + model.Extension, Size=model.Size }; response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); IHttpActionResult result = ResponseMessage(response); return result; } [Route("ImageReview"), HttpGet] public async Task<IHttpActionResult> ImageReview(Guid id) { /// Get file information my database var model = await fileService.GetByID(id); if (model == null) return BadRequest(); /// `localPath` is get from Web.Config. string localPath = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["fileServiceLocalPath"]); string root = localPath + "\\" + model.StorageName; byte[] fileData = File.ReadAllBytes(root); var stream = new MemoryStream(fileData, 0, fileData.Length); var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) }; response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/"+ model.Extension); IHttpActionResult result = ResponseMessage(response); return result; } } 文件服务 public interface IFileService { Task SendCloud(IList<FileDto> modelList, string localPath); } public class FileService : IFileService { public Task SendCloud(IList<FileDto> modelList,string localPath) { /// `ftpUserName`, `ftpPassword` and `storagePath` is get from Web.Config. string ftpUserName = ConfigurationManager.AppSettings["ftpUserName"]; string ftpPassword = ConfigurationManager.AppSettings["ftpPassword"]; string storagePath = ConfigurationManager.AppSettings["fileServiceStoragePath"]; /// Uploaded files are sent to the cloud server. foreach (var model in modelList) { FtpWebRequest req = (FtpWebRequest)WebRequest.Create(storagePath + model.StorageName); req.UseBinary = true; req.Method = WebRequestMethods.Ftp.UploadFile; req.Credentials = new NetworkCredential(ftpUserName, ftpPassword); byte[] fileData = File.ReadAllBytes(localPath + "\\" + model.StorageName); req.ContentLength = fileData.Length; Stream reqStream = req.GetRequestStream(); reqStream.Write(fileData, 0, fileData.Length); reqStream.Close(); } return Task.CompletedTask; } } 这是构建图像。 我认为你的HttpClient和MultipartFormDataContent方法应该有效 只需留意输入名称,请尝试以下操作 HttpClient httpClient = new HttpClient(); MultipartFormDataContent form = new MultipartFormDataContent(); string filename = @"E:\Uploads\demo.csv" , filename2 = @"E:\Uploads\demo2.csv" , url = "http://demo.schooling.net/school/attendance" , token = "fe60313b0edfdfaf757f9744815454545" ; byte[] bytes = System.IO.File.ReadAllBytes(filename); // Keep `token` here, no quote escaping form.Add(new StringContent(token), "token"); // Keep `Files[]` here form.Add(new ByteArrayContent(bytes), "Files[]", Path.GetFileName(filename)); // To add 2nd file, keep the input name as `Files[]` bytes = System.IO.File.ReadAllBytes(filename2); form.Add(new ByteArrayContent(bytes), "Files[]", Path.GetFileName(filename2)); var result = httpClient.PostAsync(url, form).Result;
我正在使用 ServerSocket 在 Java 中实现我自己的 HTTP 服务器。我想开始实现管道,所以我编写了一个预计首先会失败的测试。 无效 sendMultipleRequestsOnSameConnection()
如何使用HttpClient读取http标头并从HttpResponseMessage获取cookie
如何从 HttpResponseMessage 获取 cookie? 执行以下代码时出现索引越界异常。不确定问题出在哪里: 使用系统; 使用 System.Linq; 使用...
如何使用 NSubstitute 模拟 HttpClient
我正在尝试使用 NSubstitute 来模拟 HttpClient。这是代码: 公共静态 HttpClient GetHttpClient(bool isSucess = true, string methodType = "GET") { 变种
如何使用 AwsCrtHttpClient(AWS CRT HTTP 客户端?)设置 POST 请求的请求正文
我正在使用 AWS CRT HTTP 客户端创建 HTTP 请求,但我找不到设置请求正文的方法。我将 Java 11 与 AWS SDK 版本 2.27.9 结合使用。不管我如何配置这个同步...
HttpResponseMessage 文本/纯内容用引号括起来并转义
我创建了一个返回 TOML 配置文件的 webapi,当我查看 swagger/postman 中的输出时,输出正如我所期望的: [系统.“测试2”] 名称=“测试名称” 组织...
为什么对于同一请求,Postman 和 .NET MAUI 应用程序有不同的 API 响应?
我遇到了一个问题,即相同的 API 请求从 Postman 与我的 .NET MAUI 应用程序发送时返回不同的结果。有问题的 API 是一个执行验证的登录端点...
通过 Netis 路由器连接到 Jio Air Fiber 时,ESP32 HTTP 请求失败
我尝试将 ESP32 与 Jio Air Fiber 连接,但遇到了问题,因为 2.4GHz 和 5GHz Wi-Fi 通道在此路由器中不能有单独的 SSID,因此 ESP32 无法连接...
使用 Spring Web 客户端与reactor.netty HttpClient 的 API 调用超时
我正在尝试在 API 调用上设置超时,如果响应时间超过指定时间,那么我需要抛出超时异常。我正在使用 spring webclient 来进行这些 API 调用。 我找到了两种方法
为什么我在尝试通过 API 在 SharePoint 中创建文件夹时收到错误请求错误?
我试图在我的 C# 应用程序中创建一个 Sharepoint 文件夹,并不断收到 400 Bad Request 响应。我的代码似乎与我在网上找到的示例相匹配。我做错了什么? 公共异步任务
我正在尝试发出 http 请求并在 C# 控制器中的 ClearScript V8 中获取响应。当我同步运行该函数时,它工作正常。但我想异步运行它...
C# 毛伊岛代码: var uri = new URI("https://www.google.pl/"); var handler = new HttpClientHandler(); HttpClient 客户端 = new HttpClient(handler); var 响应 = 等待客户端。
要上传抖音视频文档,请指定此curl命令。但是,我下面的代码(帖子正文中包含视频路径)看起来不是处理它的正确方法。最好的转换方式是什么
通过Selenium WebDriver获取数据后使用Java的HttpClient发送HTTP请求的问题
我目前正在开发一个自动化测试套件,我使用 Selenium WebDriver 来导航 Web 应用程序并从浏览器的本地存储中检索配置数据。我可以成功...
我在调用另一个 API 时,在使用 .Net6 编写并托管在 Azure Web 应用程序上的 Web API 中遇到了 SNAT 端口耗尽的问题。我们正在使用另一个人开发的自定义库...
这是下面的代码(C#)在https://nft.storage/中上传它工作正常但是当我上传mp4文件(上传成功)时,上传的文件不起作用。源代码 https://github.com/
HttpClient PostAsync() 在 Xamarin Forms 应用程序中不起作用
在我的 Xamarin Forms 应用程序中 我正在尝试将 JSON 字符串发布到我的 Web 服务,即 RestFul API 当我使用以下代码时: 公共静态异步任务 SaveRolAsync(方法方法,角色...
这适用于 .NET 8,但在 .NET 4.8 中,对 SendAsync 的调用不会返回。我需要改变什么?谢谢 使用 (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url)) { 请求留言。
HTTPUrlConnection 与 HTTPClient 这两者之间的功能区别是什么
所以我是android的新手。我现在非常困惑。告诉我HTTPUrlConnection和HTTPClient之间有什么区别,以及从网络获取数据时哪个更好
httpclient 调用在服务器中排队,导致应用程序出现性能问题
我们有一个围绕 .NET 4.8 构建的应用程序。生产中的应用程序有 4 个服务器,并且大量使用 http 调用来获取数据。出站 http 调用是从应用程序完成的...