首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

桌面應用也能提供 HTTP 檔案下載:HttpListener 輕量實作

     編輯:關於.NET

不想為了單一檔案下載功能架設完整 IIS/ASP.NET 網站?System.Net.HttpListener 讓桌面應用 (WinForms/WPF/Console) 幾行程式碼即可啟動 HTTP 監聽器,回應下載請求。本文示範完整實作:監聽指定路徑、設定 Content-Disposition 標頭觸發瀏覽器「另存新檔」、分塊串流傳輸大檔案、中文檔名編碼處理。

核心程式碼 (WinForms 範例)


using System;
using System.IO;
using System.Net;
using System.Web; // 需參考 System.Web.dll
using System.Windows.Forms;

public partial class MainForm : Form {
  private HttpListener _listener;
  private string _filePath = @"C:\Demo\LargeFile.zip";

  private async void BtnStart_Click(object sender, EventArgs e) {
    _listener = new HttpListener();
    _listener.Prefixes.Add("https://+:8080/download/"); // 需管理員權限或預留 URL ACL
    _listener.Start();
    BtnStart.Enabled = false;
    LblStatus.Text = "監聽中... 請在瀏覽器開啟 https://localhost:8080/download/";

    try {
      var context = await _listener.GetContextAsync();
      ProcessRequest(context);
    } catch (Exception ex) {
      MessageBox.Show(ex.Message);
    } finally {
      _listener.Stop();
      BtnStart.Enabled = true;
      LblStatus.Text = "已停止";
    }
  }

  private void ProcessRequest(HttpListenerContext ctx) {
    var resp = ctx.Response;
    string fileName = Path.GetFileName(_filePath);

    // 關鍵:Content-Disposition 強制下載而非瀏覽器開啟
    resp.Headers.Add(HttpResponseHeader.ContentDisposition,
      "attachment; filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));

    resp.ContentType = "application/octet-stream";
    resp.ContentLength64 = new FileInfo(_filePath).Length;

    // 分塊串流傳輸,避免大檔案佔用記憶體
    const int BufferSize = 8192;
    byte[] buffer = new byte[BufferSize];
    using (var fs = File.OpenRead(_filePath)) {
      int read;
      while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) {
        resp.OutputStream.Write(buffer, 0, read);
      }
    }
    resp.OutputStream.Close(); // 結束回應
  }
}

關鍵細節解析

項目說明
Prefixes.Add("https://+:8080/download/")監聽所有主機名的 8080 埠,路徑含 /download/ 避免與本機 IIS 衝突。+ 需管理員權限或 netsh http add urlacl 授權。
Content-Disposition: attachment瀏覽器收到此標頭會彈出「另存新檔」對話框,而非嘗試內嵌顯示 (如 PDF/圖片)。
HttpUtility.UrlEncode中文檔名必須 UTF-8 編碼,否則瀏覽器下載時檔名會亂碼。
分塊串流 (FileStream.Read → OutputStream.Write)不將整個檔案讀入記憶體,支援 GB 級大檔案下載。
GetContextAsync非同步等待請求,不阻塞 UI 執行緒。

測試步驟

  1. 執行程式,點選檔案、按下「開始監聽」。
  2. 瀏覽器輸入 https://localhost:8080/download/ 按 Enter。
  3. 瀏覽器彈出下載對話框,檔名正確、進度條正常。

啟動監聽畫面

瀏覽器下載畫面

擴充應用場景

  • **授權檔/憑證自動分發**:客戶端輸入機器碼,桌面工具即時產生並提供下載。
  • **離線資料包匯出**:內部工具一鍵匯出資料庫快照,瀏覽器下載 ZIP。
  • **多檔案/斷點續傳**:擴充支援 Range 標頭、Accept-Ranges、多執行緒下載。
  • **驗證與授權**:於 ProcessRequest 檢查 QueryString Token 或 Basic Auth。

注意事項

  1. 埠號衝突:若 80 埠被 IIS/其他程式佔用,改用 8080、8000 等非保留埠。
  2. URL ACL:非管理員執行時,需預先執行 netsh http add urlacl url=https://+:8080/download/ user=Everyone。
  3. 防火牆:確保輸入規則允許該埠。
  4. 單一請求模型:範例僅處理一個請求即停止。生產環境應改為迴圈 while (_listener.IsListening) { var ctx = await _listener.GetContextAsync(); Task.Run(() => ProcessRequest(ctx)); }。
  5. HTTPS:需設定伺服器憑證並用 https:// 前綴,HttpListener 支援 SSL。

結語

HttpListener 是 .NET 框架內建的輕量 HTTP 伺服器,零依賴、零設定檔,極適合桌面應用內嵌簡單 HTTP 服務 (下載、回呼、Webhook 接收、健康檢查)。掌握此技術,讓桌面應用輕鬆跨越進程邊界與瀏覽器/行動裝置互動。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved