/// <summary> /// post multi-part data form to remote server /// used to upload file /// </summary> /// <param name="pUrl"></param> /// <param name="pHeaders"></param> /// <param name="pPostParams"></param> /// <param name="httpFormFile"></param> /// <param name="pProgressHandler"></param> /// <param name="pCompletionHandler"></param> public void postMultipartDataForm(string pUrl, Dictionary <string, string> pHeaders, Dictionary <string, string> pPostParams, HttpFormFile pFormFile, ProgressHandler pProgressHandler, CompletionHandler pCompletionHandler) { if (pFormFile == null) { if (pCompletionHandler != null) { pCompletionHandler(ResponseInfo.fileError(new Exception("no file specified")), ""); } return; } HttpWebRequest vWebReq = null; HttpWebResponse vWebResp = null; try { vWebReq = (HttpWebRequest)WebRequest.Create(pUrl); vWebReq.ServicePoint.Expect100Continue = false; } catch (Exception ex) { if (pCompletionHandler != null) { pCompletionHandler(ResponseInfo.invalidRequest(ex.Message), ""); } return; } try { vWebReq.UserAgent = this.getUserAgent(); vWebReq.AllowAutoRedirect = false; vWebReq.Method = "POST"; //create boundary string formBoundaryStr = this.createFormDataBoundary(); string contentType = string.Format("multipart/form-data; boundary={0}", formBoundaryStr); vWebReq.ContentType = contentType; if (pHeaders != null) { foreach (KeyValuePair <string, string> kvp in pHeaders) { if (!kvp.Key.Equals("Content-Type")) { vWebReq.Headers.Add(kvp.Key, kvp.Value); } } } //write post body vWebReq.AllowWriteStreamBuffering = true; byte[] formBoundaryBytes = Encoding.UTF8.GetBytes(string.Format("{0}{1}\r\n", FORM_BOUNDARY_TAG, formBoundaryStr)); byte[] formBoundaryEndBytes = Encoding.UTF8.GetBytes(string.Format("\r\n{0}{1}{2}\r\n", FORM_BOUNDARY_TAG, formBoundaryStr, FORM_BOUNDARY_TAG)); using (Stream vWebReqStream = vWebReq.GetRequestStream()) { //write params if (pPostParams != null) { foreach (KeyValuePair <string, string> kvp in pPostParams) { vWebReqStream.Write(formBoundaryBytes, 0, formBoundaryBytes.Length); byte[] formPartTitleData = Encoding.UTF8.GetBytes( string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n", kvp.Key)); vWebReqStream.Write(formPartTitleData, 0, formPartTitleData.Length); byte[] formPartBodyData = Encoding.UTF8.GetBytes(string.Format("\r\n{0}\r\n", kvp.Value)); vWebReqStream.Write(formPartBodyData, 0, formPartBodyData.Length); } } vWebReqStream.Write(formBoundaryBytes, 0, formBoundaryBytes.Length); //write file name string filename = pFormFile.Filename; if (string.IsNullOrEmpty(filename)) { filename = this.createRandomFilename(); } byte[] filePartTitleData = Encoding.UTF8.GetBytes( string.Format("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\r\n", filename)); vWebReqStream.Write(filePartTitleData, 0, filePartTitleData.Length); //write content type string mimeType = FORM_MIME_OCTECT; //!!!注意这里 @fengyh 2016-08-17 15:00 if (!string.IsNullOrEmpty(pFormFile.ContentType)) { mimeType = pFormFile.ContentType; } byte[] filePartMimeData = Encoding.UTF8.GetBytes(string.Format("Content-Type: {0}\r\n\r\n", mimeType)); vWebReqStream.Write(filePartMimeData, 0, filePartMimeData.Length); //write file data switch (pFormFile.BodyType) { case HttpFileType.FILE_PATH: try { FileStream fs = File.Open(pFormFile.BodyFile, FileMode.Open, FileAccess.Read); this.writeHttpRequestBody(fs, vWebReqStream); } catch (Exception fex) { if (pCompletionHandler != null) { pCompletionHandler(ResponseInfo.fileError(fex), ""); } } break; case HttpFileType.FILE_STREAM: this.writeHttpRequestBody(pFormFile.BodyStream, vWebReqStream); break; case HttpFileType.DATA_BYTES: vWebReqStream.Write(pFormFile.BodyBytes, 0, pFormFile.BodyBytes.Length); break; case HttpFileType.DATA_SLICE: vWebReqStream.Write(pFormFile.BodyBytes, pFormFile.Offset, pFormFile.Count); break; } vWebReqStream.Write(formBoundaryEndBytes, 0, formBoundaryEndBytes.Length); vWebReqStream.Flush(); } //fire request vWebResp = (HttpWebResponse)vWebReq.GetResponse(); handleWebResponse(vWebResp, pCompletionHandler); } catch (WebException wexp) { // FIX-HTTP 4xx/5xx Error 2016-11-22, 17:00 @fengyh HttpWebResponse xWebResp = wexp.Response as HttpWebResponse; handleErrorWebResponse(xWebResp, pCompletionHandler, wexp); } catch (Exception exp) { handleErrorWebResponse(vWebResp, pCompletionHandler, exp); } }
/// <summary> /// 发送格式为multipart/form-data的POST请求 /// </summary> /// <param name="url">请求Url</param> public void multipartPost(string url) { this.webRequest = (HttpWebRequest)WebRequest.CreateHttp(url); this.webRequest.UserAgent = this.getUserAgent(); this.webRequest.AllowAutoRedirect = false; this.webRequest.Method = "POST"; this.webRequest.ContentType = string.Format("{0}; boundary={1}", APPLICATION_MULTIPART_FORM, MULTIPART_BOUNDARY); //准备数据 this.postDataMemoryStream = new MemoryStream(); byte[] boundarySepTag = Encoding.UTF8.GetBytes(MULTIPART_BOUNDARY_SEP_TAG); byte[] boundaryData = Encoding.UTF8.GetBytes(MULTIPART_BOUNDARY); byte[] multiPartSepLineData = Encoding.UTF8.GetBytes(MULTIPART_SEP_LINE); //写入参数 if (this.PostArgs != null && this.PostArgs.Params != null) { foreach (KeyValuePair <string, string> kvp in this.PostArgs.Params) { //写入boundary起始标记 postDataMemoryStream.Write(boundarySepTag, 0, boundarySepTag.Length); //写入boundary postDataMemoryStream.Write(boundaryData, 0, boundaryData.Length); //写入头部和数据 postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); byte[] contentHeaderData = Encoding.UTF8.GetBytes( string.Format("Content-Disposition: form-data; name=\"{0}\"", kvp.Key)); postDataMemoryStream.Write(contentHeaderData, 0, contentHeaderData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); byte[] contentData = Encoding.UTF8.GetBytes(kvp.Value); postDataMemoryStream.Write(contentData, 0, contentData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); } } //写入文件名词和MimeType postDataMemoryStream.Write(boundarySepTag, 0, boundarySepTag.Length); postDataMemoryStream.Write(boundaryData, 0, boundaryData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); string fileName = this.PostArgs.FileName; if (string.IsNullOrEmpty(fileName)) { fileName = string.Format("RandomFileName_{0}", genId()); } byte[] fileHeaderData = Encoding.UTF8.GetBytes( string.Format("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"", fileName)); string fileContentType = "application/octet-stream"; if (!string.IsNullOrEmpty(this.PostArgs.MimeType)) { fileContentType = this.PostArgs.MimeType; } byte[] fileContentTypeData = Encoding.UTF8.GetBytes(string.Format("Content-Type: {0}", fileContentType)); postDataMemoryStream.Write(fileHeaderData, 0, fileHeaderData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); postDataMemoryStream.Write(fileContentTypeData, 0, fileContentTypeData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); //写入文件数据 if (FileContentType == PostContentType.BYTES) { postDataMemoryStream.Write(this.PostArgs.Data, 0, this.PostArgs.Data.Length); } else if (FileContentType == PostContentType.FILE) { try { using (FileStream fs = IsolatedStorageFile.GetUserStoreForApplication() .OpenFile(this.PostArgs.File, FileMode.Open, FileAccess.Read)) { byte[] buffer = new byte[BUFFER_SIZE]; int numRead = -1; while ((numRead = fs.Read(buffer, 0, buffer.Length)) != 0) { postDataMemoryStream.Write(buffer, 0, numRead); } } } catch (Exception ex) { if (this.CompletionHandler != null) { this.CompletionHandler(ResponseInfo.fileError(ex), ""); } return; } } else if (FileContentType == PostContentType.STREAM) { try { byte[] buffer = new byte[BUFFER_SIZE]; int numRead = -1; while ((numRead = this.PostArgs.Stream.Read(buffer, 0, buffer.Length)) != 0) { postDataMemoryStream.Write(buffer, 0, numRead); } } catch (Exception ex) { if (this.CompletionHandler != null) { this.CompletionHandler(ResponseInfo.fileError(ex), ""); } return; } } postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); //写入boundary结束标记 postDataMemoryStream.Write(boundarySepTag, 0, boundarySepTag.Length); postDataMemoryStream.Write(boundaryData, 0, boundaryData.Length); postDataMemoryStream.Write(boundarySepTag, 0, boundarySepTag.Length); postDataMemoryStream.Write(multiPartSepLineData, 0, multiPartSepLineData.Length); postDataMemoryStream.Flush(); //设置ContentLength this.webRequest.ContentLength = postDataMemoryStream.Length; if (this.webRequest.Headers == null) { this.webRequest.Headers = new WebHeaderCollection(); } foreach (string headerKey in this.Headers.AllKeys) { this.webRequest.Headers[headerKey] = this.Headers[headerKey]; } this.webRequest.BeginGetRequestStream(new AsyncCallback(fireMultipartPostRequest), webRequest); allDone.WaitOne(timeout); }