C# HttpWebRequest 後臺調用介面上傳大文件以及其他參數

来源:http://www.cnblogs.com/xibei/archive/2016/12/01/6123093.html
-Advertisement-
Play Games

直接上代碼,包各位看客能用!!! 1.首先請求參數的封裝 2.HttpWebRequest 封裝 HttpUploadClient類中兩個Execute2,參考網上,大都用第一個,如果上傳小文件沒問題,要是比較大(百兆以上)就會記憶體溢出,然後就用流方式。思路是一樣的 3.調用示例: 4.介面服務後臺 ...


直接上代碼,包各位看客能用!!!

1.首先請求參數的封裝

/// <summary>
    /// 上傳文件 - 請求參數類
    /// </summary>
    public class UploadParameterType
    {
        public UploadParameterType()
        {
            FileNameKey = "fileName";
            Encoding = Encoding.UTF8;
            PostParameters = new Dictionary<string, string>();
        }
        /// <summary>
        /// 上傳地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        /// 文件名稱key
        /// </summary>
        public string FileNameKey { get; set; }
        /// <summary>
        /// 文件名稱value
        /// </summary>
        public string FileNameValue { get; set; }
        /// <summary>
        /// 編碼格式
        /// </summary>
        public Encoding Encoding { get; set; }
        /// <summary>
        /// 上傳文件的流
        /// </summary>
        public Stream UploadStream { get; set; }
        /// <summary>
        /// 上傳文件 攜帶的參數集合
        /// </summary>
        public IDictionary<string, string> PostParameters { get; set; }
    }

  2.HttpWebRequest 封裝

/// <summary>
    /// Http上傳文件類 - HttpWebRequest封裝
    /// </summary>
    public class HttpUploadClient
    {
        /// <summary>
        /// 上傳執行 方法
        /// </summary>
        /// <param name="parameter">上傳文件請求參數</param>
        public static string Execute(UploadParameterType parameter)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                // 1.分界線
                string boundary = string.Format("----{0}", DateTime.Now.Ticks.ToString("x")),       // 分界線可以自定義參數
                    beginBoundary = string.Format("--{0}\r\n", boundary),
                    endBoundary = string.Format("\r\n--{0}--\r\n", boundary);
                byte[] beginBoundaryBytes = parameter.Encoding.GetBytes(beginBoundary),
                    endBoundaryBytes = parameter.Encoding.GetBytes(endBoundary);
                // 2.組裝開始分界線數據體 到記憶體流中
                memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length);
                // 3.組裝 上傳文件附加攜帶的參數 到記憶體流中
                if (parameter.PostParameters != null && parameter.PostParameters.Count > 0)
                {
                    foreach (KeyValuePair<string, string> keyValuePair in parameter.PostParameters)
                    {
                        string parameterHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n{2}", keyValuePair.Key, keyValuePair.Value, beginBoundary);
                        byte[] parameterHeaderBytes = parameter.Encoding.GetBytes(parameterHeaderTemplate);

                        memoryStream.Write(parameterHeaderBytes, 0, parameterHeaderBytes.Length);
                    }
                }
                // 4.組裝文件頭數據體 到記憶體流中
                string fileHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", parameter.FileNameKey, parameter.FileNameValue);
                byte[] fileHeaderBytes = parameter.Encoding.GetBytes(fileHeaderTemplate);
                memoryStream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length);
                // 5.組裝文件流 到記憶體流中
                byte[] buffer = new byte[1024 * 1024 * 1];
                int size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
                while (size > 0)
                {
                    memoryStream.Write(buffer, 0, size);
                    size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
                }
                // 6.組裝結束分界線數據體 到記憶體流中
                memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
                // 7.獲取二進位數據
                byte[] postBytes = memoryStream.ToArray();
                memoryStream.Close();
                GC.Collect();
                // 8.HttpWebRequest 組裝
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(parameter.Url, UriKind.RelativeOrAbsolute));
                webRequest.AllowWriteStreamBuffering = false;
                webRequest.Method = "POST";
                webRequest.Timeout = 1800000;
                webRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
                webRequest.ContentLength = postBytes.Length;
                if (Regex.IsMatch(parameter.Url, "^https://"))
                {
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                    ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
                }
                // 9.寫入上傳請求數據
                using (Stream requestStream = webRequest.GetRequestStream())
                {
                    requestStream.Write(postBytes, 0, postBytes.Length);
                    requestStream.Close();
                }
                // 10.獲取響應
                using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), parameter.Encoding))
                    {
                        string body = reader.ReadToEnd();
                        reader.Close();
                        return body;
                    }
                }
            }
        }
        /// <summary>
        /// 上傳執行 方法
        /// </summary>
        /// <param name="parameter">上傳文件請求參數</param>
        public static string Execute2(UploadParameterType parameter)
        {
            // 1.分界線
            string boundary = string.Format("----{0}", DateTime.Now.Ticks.ToString("x")),       // 分界線可以自定義參數
                beginBoundary = string.Format("--{0}\r\n", boundary),
                endBoundary = string.Format("\r\n--{0}--\r\n", boundary);
            byte[] beginBoundaryBytes = parameter.Encoding.GetBytes(beginBoundary),
                endBoundaryBytes = parameter.Encoding.GetBytes(endBoundary);
            byte[] postBytes = new byte[] { };
            using (MemoryStream memoryStream = new MemoryStream())
            {
                // 2.組裝開始分界線數據體 到記憶體流中
                memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length);
                // 3.組裝 上傳文件附加攜帶的參數 到記憶體流中
                if (parameter.PostParameters != null && parameter.PostParameters.Count > 0)
                {
                    foreach (KeyValuePair<string, string> keyValuePair in parameter.PostParameters)
                    {
                        string parameterHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n{2}", keyValuePair.Key, keyValuePair.Value, beginBoundary);
                        byte[] parameterHeaderBytes = parameter.Encoding.GetBytes(parameterHeaderTemplate);
                        memoryStream.Write(parameterHeaderBytes, 0, parameterHeaderBytes.Length);
                    }
                }
                // 4.組裝文件頭數據體 到記憶體流中
                string fileHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", parameter.FileNameKey, parameter.FileNameValue);
                byte[] fileHeaderBytes = parameter.Encoding.GetBytes(fileHeaderTemplate);
                memoryStream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length);

                // 5.組裝結束分界線數據體 到記憶體流中
                //memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
                // 6.獲取二進位數據
                postBytes = memoryStream.ToArray();
            }
            // 7.HttpWebRequest 組裝
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(parameter.Url, UriKind.RelativeOrAbsolute));
            //對發送的數據不使用緩存【重要、關鍵】
            webRequest.AllowWriteStreamBuffering = false;
            webRequest.Method = "POST";
            webRequest.Timeout = 1800000;
            webRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            webRequest.ContentLength = postBytes.Length + parameter.UploadStream.Length+endBoundaryBytes.Length;
            if (Regex.IsMatch(parameter.Url, "^https://"))
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
            }
            // 8.組裝文件流
            byte[] buffer = new byte[1024 * 1024 * 1];
            int size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
            Stream requestStream = webRequest.GetRequestStream();
            requestStream.Write(postBytes, 0, postBytes.Length);
            while (size > 0)
            {
                requestStream.Write(buffer, 0, size);
                size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
            }
            requestStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
            requestStream.Close();
            // 9.獲取響應
            using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
            {
                using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), parameter.Encoding))
                {
                    string body = reader.ReadToEnd();
                    reader.Close();
                    return body;
                }
            }
        }
        static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }


    }

  HttpUploadClient類中兩個Execute2,參考網上,大都用第一個,如果上傳小文件沒問題,要是比較大(百兆以上)就會記憶體溢出,然後就用流方式。思路是一樣的

3.調用示例:

            using (FileStream fs = new FileStream(@"C:\\test.zip", FileMode.Open, FileAccess.Read))
            {
                Dictionary<string, string> postParameter = new Dictionary<string, string>();
                postParameter.Add("name", "heshang");
                postParameter.Add("param", "1 2 3");
                string result = HttpUploadClient.Execute(new UploadParameterType
                {
                    Url = url,
                    UploadStream = fs,
                    FileNameValue = "test.zip",
                    PostParameters = postParameter
                });
            }

  4.介面服務後臺接受請求時:

public IHttpActionResult Post()
        {
            HttpPostedFile file = HttpContext.Current.Request.Files[0];
            string pyPath = HttpContext.Current.Request["name"];
            string Params = HttpContext.Current.Request["params"];
            file.SaveAs("C:\\test.zip");
            return Ok("");
        }

  5.完美解決大文件上傳


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 系統環境:Centos7 第一步安裝NodeJS 建議採用穩定編譯過的版本,source code稍麻煩,編譯過的直接可用,安裝超級簡單 下載完成後安裝成功 第二步:安裝PM2 正常情況我看到的是簡書上的 http://www.jianshu.com/p/fdc12d82b661 我的centos就 ...
  • Linux系統裁剪筆記 1.什麼裁剪? 本篇文章的主要目的是讓筆者和讀者更深的認識Linux系統的運作方式,大致內容就是把Linux拆開自己一個個組件來組裝,然後完成一個微型的Linux系統.下麵,讓我們來實現吧..寫的不好的地方請指教. 2.原理 大家都知道,操作系統的啟動流程是(主要是Linux ...
  • 最近的想要用android手機藍牙共用wifi網路給ubuntu16.04系統用,查了好多資料,發現網上很少有有用的。自己實踐後分享如下。 第一步:手機與電腦配對: 該步驟比較簡單,網上也可以找到相關的資料,大致步驟記錄如下(因手機不同略有不同): (1)打開手機藍牙,設置為對周圍設備可見(因手機不 ...
  • 前兩天入手一個Macbook air,在裝軟體過程中摸索了一些基本操作,現就常用操作進行總結, 1關於觸控板: 按下(不區分左右) =滑鼠左鍵 control+按下 =滑鼠右鍵 雙指上下拖 滾屏 雙指左右拖 瀏覽器前進/後退 三指左右拖 切換程式 三指上下拖 打開程式縮略圖/恢復 四指抓 打開所有程 ...
  • Hadoop的安裝非常簡單,可以在官網上下載到最近的幾個版本,最好使用穩定版。本例在3台機器集群安裝。hadoop版本如下: Hadoop的安裝非常簡單,可以在官網上下載到最近的幾個版本,最好使用穩定版。本例在3台機器集群安裝。hadoop版本如下: Hadoop的安裝非常簡單,可以在官網上下載到最 ...
  • .NET基礎知識點 l .Net平臺 .Net FrameWork框架 l .Net FrameWork框架提供了一個穩定的運行環境,;來保障我們.Net平臺正常的運轉 l 兩種交互模式 C/S:要求客戶的電腦上必須要安裝一個客戶端:qq、360、快播等..... B/S:要求客戶的電腦上只需要安裝 ...
  • "原文地址 Kestrel server for ASP.NET Core" By [Tom Dykstra][1], [Chris Ross][2], and [Stephen Halter][3] Kestrel是一個基於libuv的跨平臺[ASP.NET Core web伺服器][4],[li ...
  • 公司還用這些老家伙沒辦法,用了幾次這倆。每次用都要重新翻一下A片。 好好的A片楞是翻譯成了禪經。把這東西弄成個玄學。微軟也是吃棗藥丸。參考了@風中靈藥的blog.寫的牛逼。 還有一些公司用到的風中靈藥沒有提及,我給自己留個tip.好以後看看。有錯誤希望大家指出。雖然我不一定改。 AutoResetE ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...