由于IIS站點權限等問題,總是沒找到處理辦法,所以改用外掛的winform的方式來下載共享文件(也可以改為使用windows服務的方式)。
前提需要先在資源管理器中登錄到共享文件夾,確保系統能訪問。
- 服務端代碼 (.NET后端)
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Web;public class FileDownloadService
{private const int WinFormPort = 11000;public void DownloadFile(string filePath){try{// 1. 連接到WinForm客戶端using (TcpClient client = new TcpClient("127.0.0.1", WinFormPort))using (NetworkStream netStream = client.GetStream()){// 2. 發送文件路徑byte[] pathData = Encoding.UTF8.GetBytes(filePath);netStream.Write(pathData, 0, pathData.Length);// 3. 設置響應頭Response.Clear();Response.ContentType = "application/octet-stream";Response.AddHeader("Content-Disposition", $"attachment; filename={HttpUtility.UrlEncode(Path.GetFileName(filePath))}");// 4. 流式傳輸到客戶端瀏覽器byte[] buffer = new byte[1024 * 1024]; // 1MB緩沖區int bytesRead;while ((bytesRead = netStream.Read(buffer, 0, buffer.Length)) > 0){Response.OutputStream.Write(buffer, 0, bytesRead);Response.Flush();}}}catch (Exception ex){Response.Write($"下載錯誤: {ex.Message}");}finally{Response.End();}}
}
- WinForm客戶端代碼
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;public class FileTransferService : IDisposable
{private TcpListener _listener;private const int Port = 11000;private bool _isRunning;public void Start(){_isRunning = true;_listener = new TcpListener(IPAddress.Loopback, Port);_listener.Start(10); // 允許10個等待連接BeginAcceptClient();}private void BeginAcceptClient(){if (_isRunning){_listener.BeginAcceptTcpClient(ClientHandler, null);}}private void ClientHandler(IAsyncResult ar){TcpClient client = null;try{client = _listener.EndAcceptTcpClient(ar);ThreadPool.QueueUserWorkItem(ProcessClient, client);}catch (Exception ex){client?.Dispose();MessageBox.Show($"接受連接錯誤: {ex.Message}");}finally{BeginAcceptClient(); // 繼續監聽新連接}}private void ProcessClient(object state){using (TcpClient client = (TcpClient)state){try{client.SendTimeout = 30000; // 30秒發送超時client.ReceiveTimeout = 30000; // 30秒接收超時using (NetworkStream netStream = client.GetStream()){// 1. 接收文件路徑byte[] buffer = new byte[1024];int received = netStream.Read(buffer, 0, buffer.Length);string filePath = Encoding.UTF8.GetString(buffer, 0, received);// 2. 檢查文件是否存在if (!File.Exists(filePath)){byte[] error = Encoding.UTF8.GetBytes("FILE_NOT_FOUND");netStream.Write(error, 0, error.Length);return;}// 3. 分塊讀取文件并傳輸using (FileStream fs = File.OpenRead(filePath)){byte[] fileBuffer = new byte[1024 * 1024]; // 1MB緩沖區int bytesRead;while ((bytesRead = fs.Read(fileBuffer, 0, fileBuffer.Length)) > 0){netStream.Write(fileBuffer, 0, bytesRead);}}}}catch (Exception ex){try{byte[] error = Encoding.UTF8.GetBytes($"ERROR:{ex.Message}");client.GetStream().Write(error, 0, error.Length);}catch { /* 忽略二次錯誤 */ }}}}public void Stop(){_isRunning = false;_listener?.Stop();}public void Dispose(){Stop();_listener?.Dispose();}
}
- WinForm界面
public partial class MainForm : Form
{private FileTransferService _fileService;public MainForm(){InitializeComponent();_fileService = new FileTransferService();_fileService.Start();}protected override void OnFormClosing(FormClosingEventArgs e){_fileService.Dispose();base.OnFormClosing(e);}private void btnStart_Click(object sender, EventArgs e){_fileService.Start();lblStatus.Text = "服務已啟動 (端口:11000)";}private void btnStop_Click(object sender, EventArgs e){_fileService.Stop();lblStatus.Text = "服務已停止";}
}
Windows查看端口是否被占用
netstat -ano | findstr "端口號"