zoukankan      html  css  js  c++  java
  • C#开发BIMFACE系列5 服务端API之文件直传

    BIMFACE使用了分布式对象存储来存储用户上传的模型/图纸文件。如使用普通的文件上传接口, 文件流会通过BIMFACE的服务器,再流向最终的分布式存储系统,整个上传过程会受BIMFACE服务器的带宽限制,上传速度非最优。 如使用文件直传接口,开发者应用在申请到一个Policy凭证后,可以直接上传文件跟BIMFACE后台的分布式存储系统, 这样上传速度和稳定性都会有提升,是我们推荐的上传方式。

    另外,很多BIMFACE应用都有自己的Web前端页面,这种情况我们也推荐使用文件直传接口。

    文件直传的逻辑图如下:

    使用流程如下:
    1. 开发者应用向 BIMFACE 申请上传 Policy 请求。

    2. BIMFACE 返回上传 Policy 和签名给开发者应用。

    3. 开发者应用使用在第二个步骤中获取的 URL 信息,直接上传文件数据到 BIMFACE 后端的分布式对象存储。

    步骤一:获取文件直传的policy凭证

    请求地址:GET https://file.bimface.com/upload/policy

    请求参数:

    请求 path(示例):https://file.bimface.com/upload/policy?name=example.rvt

    请求 header(示例):"Authorization: Bearer dc671840-bacc-4dc5-a134-97c1918d664b"

    HTTP响应示例(200):

    C#实现方法:application/octet-stream

     1 /// <summary>
     2 ///  获取文件直传的policy凭证
     3 /// </summary>
     4 /// <param name="accessToken">令牌</param>
     5 /// <param name="fileName">【必填】文件的全名</param>
     6 /// <param name="sourceId">【可选】调用方的文件源ID,不能重复</param>
     7 /// <returns></returns>
     8 public virtual FileUploadPolicyResponse GetFileUploadPolicy(string accessToken, string fileName, string sourceId = "")
     9 {
    10     /*  BIMFACE 使用了分布式对象存储来存储用户上传的模型/图纸文件。
    11         如使用普通的文件上传接口,文件流会通过BIMFACE的服务器,再流向最终的分布式存储系统,整个上传过程会受BIMFACE服务器的带宽限制,上传速度非最优。 
    12         如使用文件直传接口,开发者应用在申请到一个Policy凭证后,可以直接上传文件跟BIMFACE后台的分布式存储系统, 
    13         这样上传速度和稳定性都会有提升,是我们推荐的上传方式。 
    14      */
    15 
    16     /* 使用流程如下:
    17         1、开发者应用向BIMFACE申请上传Policy请求
    18         2、BIMFACE返回上传Policy和签名给开发者应用。
    19      */
    20 
    21     //GET https://file.bimface.com/upload/policy 。例如:https://file.bimface.com/upload/policy?name=example.rvt
    22     string url = string.Format(BimfaceConstants.FILE_HOST + "/upload/policy?name={0}", fileName.UrlEncode(Encoding.UTF8)); //文件的全名,使用URL编码(UTF-8),最多256个字符
    23     if (sourceId.IsNotNullAndWhiteSpace())
    24     {
    25         url = url + "&sourceId=" + sourceId;
    26     }
    27 
    28     BimFaceHttpHeaders headers = new BimFaceHttpHeaders();
    29     headers.AddOAuth2Header(accessToken);
    30 
    31     try
    32     {
    33         FileUploadPolicyResponse response;
    34 
    35         HttpManager httpManager = new HttpManager(headers);
    36         HttpResult httpResult = httpManager.Get(url);
    37         if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    38         {
    39             response = httpResult.Text.DeserializeJsonToObject<FileUploadPolicyResponse>();
    40         }
    41         else
    42         {
    43             response = new FileUploadPolicyResponse
    44             {
    45                 Message = httpResult.RefText
    46             };
    47         }
    48 
    49         return response;
    50     }
    51     catch (Exception ex)
    52     {
    53         throw new Exception("获取文件直传的policy凭证时发生异常!", ex);
    54     }
    55 }

    其中引用的 httpManager.Get() 方法如下:

     1 /// <summary>
     2 /// HTTP-GET方法,(不包含body数据)。
     3 /// 发送 HTTP 请求并返回来自 Internet 资源的响应(HTML代码)
     4 /// </summary>
     5 /// <param name="url">请求目标URL</param>
     6 /// <returns>HTTP-GET的响应结果</returns>
     7 public HttpResult Get(string url)
     8 {
     9     return RequestString(url, null, WebRequestMethods.Http.Get, null);
    10 }
     1 /// <summary>
     2 ///  HTTP请求(包含文本的body数据)
     3 /// </summary>
     4 /// <param name="url">请求目标URL</param>
     5 /// <param name="data">主体数据(普通文本或者JSON文本)。如果参数中有中文,请使用合适的编码方式进行编码,例如:gb2312或者utf-8</param>
     6 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
     7 /// <param name="contentType"><see langword="Content-type" /> HTTP 标头的值。请使用 ContentType 类的常量来获取</param>
     8 /// <returns></returns>
     9 private HttpResult RequestString(string url, string data, string method, string contentType)
    10 {
    11     HttpResult httpResult = new HttpResult();
    12     HttpWebRequest httpWebRequest = null;
    13 
    14     try
    15     {
    16         httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
    17         httpWebRequest.Method = method;
    18         httpWebRequest.Headers = HeaderCollection;
    19         httpWebRequest.CookieContainer = CookieContainer;
    20         if (!string.IsNullOrWhiteSpace(contentType))
    21         {
    22             httpWebRequest.ContentType = contentType;// 此属性的值存储在WebHeaderCollection中。如果设置了WebHeaderCollection,则属性值将丢失。所以放置在Headers 属性之后设置
    23         }
    24         httpWebRequest.UserAgent = _userAgent;
    25         httpWebRequest.AllowAutoRedirect = _allowAutoRedirect;
    26         httpWebRequest.ServicePoint.Expect100Continue = false;
    27 
    28         if (data != null)
    29         {
    30             httpWebRequest.AllowWriteStreamBuffering = true;
    31             using (Stream requestStream = httpWebRequest.GetRequestStream())
    32             {
    33                 requestStream.Write(EncodingType.GetBytes(data), 0, data.Length);//将请求参数写入请求流中
    34                 requestStream.Flush();
    35             }
    36         }
    37 
    38         HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
    39         if (httpWebResponse != null)
    40         {
    41             GetResponse(ref httpResult, httpWebResponse);
    42             httpWebResponse.Close();
    43         }
    44     }
    45     catch (WebException webException)
    46     {
    47         GetWebExceptionResponse(ref httpResult, webException);
    48     }
    49     catch (Exception ex)
    50     {
    51         GetExceptionResponse(ref httpResult, ex, method, contentType);
    52     }
    53     finally
    54     {
    55         if (httpWebRequest != null)
    56         {
    57             httpWebRequest.Abort();
    58         }
    59     }
    60 
    61     return httpResult;
    62 }
    View Code
    步骤二:根据policy凭证在web端上传文件

    通过接口“https://file.bimface.com/upload/policy”获取文件直传的policy凭证后,可以直接在前端使用表单上传方式将文件上传到BIMFACE的对象存储上。

    BIMFACE 控制台就是通过这种方式来实现文件上传的,可以F12→network查看请求详情。Form Data 数据格式如下:

     1 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
     2 Content-Disposition: form-data; name="key"
     3 
     4 847adf52871d4c25a23424942f7f4c1d
     5 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
     6 Content-Disposition: form-data; name="policy"
     7 
     8 eyJleHBpcmF0aW9uIjoiMjAxOS0wOC0yOFQxMjo1MjoyMi4wMjVaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA3Mzc0MTgyNF0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDAifSxbInN0YXJ0cy13aXRoIiwiJGtleSIsIiJdXX0=
     9 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    10 Content-Disposition: form-data; name="OSSAccessKeyId"
    11 
    12 5nGlEwOIzrwCVaDZ
    13 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    14 Content-Disposition: form-data; name="success_action_status"
    15 
    16 200
    17 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    18 Content-Disposition: form-data; name="callback"
    19 
    20 eyJjYWxsYmFja1VybCI6Imh0dHBzOi8vZmlsZS5iaW1mYWNlLmNvbS9vc3MvcmVjZWl2ZSIsImNhbGxiYWNrSG9zdCI6ImZpbGUuYmltZmFjZS5jb20iLCJjYWxsYmFja0JvZHkiOiJvYmplY3RcdTAwM2Qke29iamVjdH1cdTAwMjZzaXplXHUwMDNkJHtzaXplfVx1MDAyNmV0YWdcdTAwM2Qke2V0YWd9XHUwMDI2bmFtZVx1MDAzZDAxX0JJTUZBQ0UlRTclQTQlQkElRTQlQkUlOEIlRTYlOTYlODclRTQlQkIlQjYtUmV2aXQlRTYlQTglQTElRTUlOUUlOEIucnZ0XHUwMDI2ZmlsZUlkXHUwMDNkMTY4MTM0ODIwMDAyMzUyMFx1MDAyNmFwcGtleVx1MDAzZEh0em92SmdpQWxWNkZvOVczbnZ3eW1zb2NZNXc5c0pSXHUwMDI2c291cmNlSWRcdTAwM2Q1ODNlMWNkOWJiNzc0YTdjOGNhMzlhN2I3YzJlZDEwOFx1MDAyNmZpbGVCdWNrZXRcdTAwM2RiZi1wcm9kLXNyY2ZpbGUiLCJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIn0=
    21 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    22 Content-Disposition: form-data; name="signature"
    23 
    24 /njtosIn/4EkOWqpVNW/8Dlu73E=
    25 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    26 Content-Disposition: form-data; name="id"
    27 
    28 WU_FILE_0
    29 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    30 Content-Disposition: form-data; name="name"
    31 
    32 01_BIMFACE示例文件-Revit模型.rvt
    33 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    34 Content-Disposition: form-data; name="type"
    35 
    36 application/octet-stream
    37 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    38 Content-Disposition: form-data; name="lastModifiedDate"
    39 
    40 Thu Aug 01 2019 17:06:54 GMT+0800 (中国标准时间)
    41 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    42 Content-Disposition: form-data; name="size"
    43 
    44 6459392
    45 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU
    46 Content-Disposition: form-data; name="file"; filename="01_BIMFACE示例文件-Revit模型.rvt"
    47 Content-Type: application/octet-stream
    48 
    49 
    50 ------WebKitFormBoundaryBSvYqSMAnAcFeGAU--
    View Code

    以获取到的policy凭证为以下数据示例:

    通过表单方式上传时,请求的构造方式为:

    请求示例:使用Postman测试上传到BIMFACE的后台即阿里云服务器

    Postman 给出的 HTTP 的multipart/form-data 的数据格式并不正确。

    关于 multipart/form-data 的正确的数据格式请参考:

    C# HTTP系列 HttpWebRequest 与 HttpWebResponse

    C# HTTP系列13 以form-data方式上传多个文件以及键值对集合到远程服务器

    C#实现方法:

     1 /// <summary>
     2 ///  通过文件直传的policy凭证,直接上传文件【推荐使用该方式】
     3 /// </summary>
     4 /// <param name="accessToken">令牌</param>
     5 /// <param name="fileFullName">【必填】待上传的文件(包含全路径的完全限定名)</param>
     6 /// <returns></returns>
     7 public FileUploadResponse UploadFileByPolicy(string accessToken, string fileFullName)
     8 {
     9     /* BIMFACE使用了分布式对象存储来存储用户上传的模型/图纸文件。
    10        如使用普通的文件上传接口,文件流会通过BIMFACE的服务器,再流向最终的分布式存储系统,整个上传过程会受BIMFACE服务器的带宽限制,上传速度非最优。 
    11        如使用文件直传接口,开发者应用在申请到一个Policy凭证后,可以直接上传文件跟BIMFACE后台的分布式存储系统, 
    12        这样上传速度和稳定性都会有提升,是我们推荐的上传方式。 
    13     */
    14 
    15     /* 使用流程如下:
    16         1、开发者应用向BIMFACE申请上传Policy请求。
    17         2、BIMFACE返回上传Policy和签名给开发者应用。
    18         3、开发者应用使用在第二个步骤中获取的URL信息,直接上传文件数据到BIMFACE后端的分布式对象存储。
    19      */
    20     FileUploadResponse response = null;
    21     try
    22     {
    23         FileInfo fileInfo = new FileInfo(fileFullName);
    24         string fileName = fileInfo.Name;
    25 
    26         FileUploadPolicyResponse policyResponse = GetFileUploadPolicy(accessToken, fileName);
    27         if (policyResponse.Code == HttpResult.STATUS_SUCCESS)
    28         {
    29             string url = policyResponse.Data.Host;
    30 
    31             /* Dictionary 字典中 key 是关键字,不能添加进去。所以添加了响应的后缀 _BIMFACE_,解析时再去除后缀 */
    32             NameValueCollection kVDatas = new NameValueCollection();
    33             kVDatas.Add("name" + StringUtils.Symbol.KEY_SUFFIX, fileName);
    34             kVDatas.Add("key" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.ObjectKey);
    35             kVDatas.Add("policy" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.Policy);
    36             kVDatas.Add("OSSAccessKeyId" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.AccessId);
    37             kVDatas.Add("success_action_status" + StringUtils.Symbol.KEY_SUFFIX, "200");
    38             kVDatas.Add("callback" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.CallbackBody);
    39             kVDatas.Add("signature" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.Signature);
    40 
    41             HttpManager httpManager = new HttpManager();
    42             HttpResult httpResult = httpManager.UploadFormByMultipart(url, fileFullName, kVDatas);
    43             if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    44             {
    45                 response = httpResult.Text.DeserializeJsonToObject<FileUploadResponse>();
    46             }
    47             else
    48             {
    49                 response = new FileUploadResponse
    50                 {
    51                     Message = httpResult.RefText
    52                 };
    53             }
    54         }
    55 
    56         return response;
    57     }
    58     catch (Exception ex)
    59     {
    60         throw new Exception("通过文件直传的policy凭证,直接上传文件时发生异常!", ex);
    61     }
    62 }
    其中引用的 httpManager.UploadFormByMultipart() 方法如下:
     1 /// <summary>
     2 /// HTTP请求(包含多分部数据,multipart/form-data)。
     3 /// 将文件以及多个参数以多分部数据表单方式上传到指定url的服务器
     4 /// </summary>
     5 /// <param name="url">请求目标URL</param>
     6 /// <param name="fileFullName">待上传的文件(包含全路径的完全限定名)</param>
     7 /// <param name="kVDatas">请求时表单键值对数据。</param>
     8 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
     9 /// <param name="timeOut">获取或设置 <see cref="M:System.Net.HttpWebRequest.GetResponse" />10 ///                       <see cref="M:System.Net.HttpWebRequest.GetRequestStream" /> 方法的超时值(以毫秒为单位)。
    11 ///                       -1 表示永不超时
    12 /// </param>
    13 /// <returns></returns>
    14 public HttpResult UploadFormByMultipart(string url, string fileFullName, NameValueCollection kVDatas = null, string method = WebRequestMethods.Http.Post, int timeOut = -1)
    15 {
    16     string[] fileFullNames = { fileFullName };
    17 
    18     return UploadFormByMultipart(url, fileFullNames, kVDatas, method, timeOut);
    19 }
    
    
      1 /// <summary>
      2 /// HTTP请求(包含多分部数据,multipart/form-data)。
      3 /// 将多个文件以及多个参数以多分部数据表单方式上传到指定url的服务器
      4 /// </summary>
      5 /// <param name="url">请求目标URL</param>
      6 /// <param name="fileFullNames">待上传的文件列表(包含全路径的完全限定名)。如果某个文件不存在,则忽略不上传</param>
      7 /// <param name="kVDatas">请求时表单键值对数据。</param>
      8 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
      9 /// <param name="timeOut">获取或设置 <see cref="M:System.Net.HttpWebRequest.GetResponse" /> 10 ///                       <see cref="M:System.Net.HttpWebRequest.GetRequestStream" /> 方法的超时值(以毫秒为单位)。
     11 ///                       -1 表示永不超时
     12 /// </param>
     13 /// <returns></returns>
     14 public HttpResult UploadFormByMultipart(string url, string[] fileFullNames, NameValueCollection kVDatas = null, string method = WebRequestMethods.Http.Post, int timeOut = -1)
     15 {
     16     #region 说明
     17     /* 阿里云文档:https://www.alibabacloud.com/help/zh/doc-detail/42976.htm
     18        C# 示例:  https://github.com/aliyun/aliyun-oss-csharp-sdk/blob/master/samples/Samples/PostPolicySample.cs?spm=a2c63.p38356.879954.18.7f3f7c34W3bR9U&file=PostPolicySample.cs
     19                  (C#示例中仅仅是把文件中的文本内容当做 FormData 中的项,与文件流是不一样的。本方法展示的是文件流,更通用)
     20       */
     21 
     22     /* 说明:multipart/form-data 方式提交文件
     23      *     (1) Header 一定要有 Content-Type: multipart/form-data; boundary={boundary}。
     24      *     (2) Header 和bod y之间由 
    --{boundary} 分割。
     25      *     (3) 表单域格式 :Content-Disposition: form-data; name="{key}"
    
    
     26      *                   {value}
    
     27      *                   --{boundary}
     28      *     (4)表单域名称大小写敏感,如policy、key、file、OSSAccessKeyId、OSSAccessKeyId、Content-Disposition。
     29      *     (5)注意:表单域 file 必须为最后一个表单域。即必须放在最后写。
     30      */
     31     #endregion
     32 
     33     #region ContentType 说明
     34     /* 该ContentType的属性包含请求的媒体类型。分配给ContentType属性的值在请求发送Content-typeHTTP标头时替换任何现有内容。
     35        
     36        要清除Content-typeHTTP标头,请将ContentType属性设置为null。
     37        
     38      * 注意:此属性的值存储在WebHeaderCollection中。如果设置了WebHeaderCollection,则属性值将丢失。
     39      *      所以放置在Headers 属性之后设置
     40      */
     41     #endregion
     42 
     43     #region Method 说明
     44     /* 如果 ContentLength 属性设置为-1以外的任何值,则必须将 Method 属性设置为上载数据的协议属性。 */
     45     #endregion
     46 
     47     #region HttpWebRequest.CookieContainer 在 .NET3.5 与 .NET4.0 中的不同
     48     /* 请参考:https://www.crifan.com/baidu_emulate_login_for_dotnet_4_0_error_the_fisrt_two_args_should_be_string_type_0_1/ */
     49     #endregion
     50 
     51     HttpResult httpResult = new HttpResult();
     52 
     53     #region 校验
     54 
     55     if (fileFullNames == null || fileFullNames.Length == 0)
     56     {
     57         httpResult.Status = HttpResult.STATUS_FAIL;
     58 
     59         httpResult.RefCode = (int)HttpStatusCode2.USER_FILE_NOT_EXISTS;
     60         httpResult.RefText = HttpStatusCode2.USER_FILE_NOT_EXISTS.GetCustomAttributeDescription();
     61 
     62         return httpResult;
     63     }
     64 
     65     List<string> lstFiles = new List<string>();
     66     foreach (string fileFullName in fileFullNames)
     67     {
     68         if (File.Exists(fileFullName))
     69         {
     70             lstFiles.Add(fileFullName);
     71         }
     72     }
     73 
     74     if (lstFiles.Count == 0)
     75     {
     76         httpResult.Status = HttpResult.STATUS_FAIL;
     77 
     78         httpResult.RefCode = (int)HttpStatusCode2.USER_FILE_NOT_EXISTS;
     79         httpResult.RefText = HttpStatusCode2.USER_FILE_NOT_EXISTS.GetCustomAttributeDescription();
     80 
     81         return httpResult;
     82     }
     83 
     84     #endregion
     85 
     86     string boundary = CreateFormDataBoundary();                                         // 边界符
     87     byte[] beginBoundaryBytes = Encoding.UTF8.GetBytes("--" + boundary + "
    ");     // 边界符开始。【☆】右侧必须要有 
     。
     88     byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("
    --" + boundary + "--
    "); // 边界符结束。【☆】两侧必须要有 --
     。
     89     byte[] newLineBytes = Encoding.UTF8.GetBytes("
    "); //换一行
     90     MemoryStream memoryStream = new MemoryStream();
     91 
     92     HttpWebRequest httpWebRequest = null;
     93     try
     94     {
     95         httpWebRequest = WebRequest.Create(url) as HttpWebRequest; // 创建请求
     96         httpWebRequest.ContentType = string.Format(HttpContentType.MULTIPART_FORM_DATA + "; boundary={0}", boundary);
     97         //httpWebRequest.Referer = "http://bimface.com/user-console";
     98         httpWebRequest.Method = method;
     99         httpWebRequest.KeepAlive = true;
    100         httpWebRequest.Timeout = timeOut;
    101         httpWebRequest.UserAgent = GetUserAgent();
    102 
    103         #region 步骤1:写入键值对
    104         if (kVDatas != null)
    105         {
    106             string formDataTemplate = "Content-Disposition: form-data; name="{0}"
    
    " +
    107                                       "{1}
    ";
    108 
    109             foreach (string key in kVDatas.Keys)
    110             {
    111                 string formItem = string.Format(formDataTemplate, key.Replace(StringUtils.Symbol.KEY_SUFFIX, String.Empty), kVDatas[key]);
    112                 byte[] formItemBytes = Encoding.UTF8.GetBytes(formItem);
    113 
    114                 memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length); // 1.1 写入FormData项的开始边界符
    115                 memoryStream.Write(formItemBytes, 0, formItemBytes.Length);           // 1.2 将键值对写入FormData项中
    116             }
    117         }
    118         #endregion
    119 
    120         #region 步骤2:写入文件(表单域 file 必须为最后一个表单域)
    121 
    122         const string filePartHeaderTemplate = "Content-Disposition: form-data; name="{0}"; filename="{1}"
    " +
    123                                               "Content-Type: application/octet-stream
    
    ";
    124 
    125         int i = 0;
    126         foreach (var fileFullName in lstFiles)
    127         {
    128             FileInfo fileInfo = new FileInfo(fileFullName);
    129             string fileName = fileInfo.Name;
    130 
    131             string fileHeaderItem = string.Format(filePartHeaderTemplate, "file", fileName);
    132             byte[] fileHeaderItemBytes = Encoding.UTF8.GetBytes(fileHeaderItem);
    133 
    134             if (i > 0)
    135             {
    136                 // 第一笔及第一笔之后的数据项之间要增加一个换行 
    137                 memoryStream.Write(newLineBytes, 0, newLineBytes.Length);
    138             }
    139             memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length);      // 2.1 写入FormData项的开始边界符
    140             memoryStream.Write(fileHeaderItemBytes, 0, fileHeaderItemBytes.Length);    // 2.2 将文件头写入FormData项中
    141 
    142             int bytesRead;
    143             byte[] buffer = new byte[1024];
    144 
    145             FileStream fileStream = new FileStream(fileFullName, FileMode.Open, FileAccess.Read);
    146             while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
    147             {
    148                 memoryStream.Write(buffer, 0, bytesRead);                              // 2.3 将文件流写入FormData项中
    149             }
    150 
    151             i++;
    152         }
    153 
    154         memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);             // 2.4 写入FormData的结束边界符
    155 
    156         #endregion
    157 
    158         #region 步骤3:将表单域(内存流)写入 httpWebRequest 的请求流中,并发起请求
    159         httpWebRequest.ContentLength = memoryStream.Length;
    160 
    161         Stream requestStream = httpWebRequest.GetRequestStream();
    162 
    163         memoryStream.Position = 0;
    164         byte[] tempBuffer = new byte[memoryStream.Length];
    165         memoryStream.Read(tempBuffer, 0, tempBuffer.Length);
    166         memoryStream.Close();
    167 
    168         requestStream.Write(tempBuffer, 0, tempBuffer.Length);        // 将内存流中的字节写入 httpWebRequest 的请求流中
    169         requestStream.Close();
    170         #endregion
    171 
    172         HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应
    173         if (httpWebResponse != null)
    174         {
    175             //GetHeaders(ref httpResult, httpWebResponse);
    176             GetResponse(ref httpResult, httpWebResponse);
    177             httpWebResponse.Close();
    178         }
    179     }
    180     catch (WebException webException)
    181     {
    182         GetWebExceptionResponse(ref httpResult, webException);
    183     }
    184     catch (Exception ex)
    185     {
    186         GetExceptionResponse(ref httpResult, ex, method, HttpContentType.MULTIPART_FORM_DATA);
    187     }
    188     finally
    189     {
    190         if (httpWebRequest != null)
    191         {
    192             httpWebRequest.Abort();
    193         }
    194     }
    195 
    196     return httpResult;
    197 }
     
  • 相关阅读:
    [Swift]todoList压栈
    Backtrack下的dns爆破工具的目录
    Linux如何设置dns
    预防黑客入侵 防黑必学的cmd命令vs网络安全
    SSL协议详解
    CDN(内容分发网络)技术原理
    社工数据搜索引擎搭建
    实战 SSH 端口转发
    Sublime Text编辑器如何隐藏顶部的菜单栏
    Sublime Text 2 -Sidebar 背景色调整为黑色
  • 原文地址:https://www.cnblogs.com/SavionZhang/p/11425945.html
Copyright © 2011-2022 走看看