C# 如何通过 TCP 为 HTTP 发送文件?

C# How do you send a file via TCP for HTTP?

我目前面临的问题是我无法让我的 C# 程序写入我想在响应中发送的文件(我正在写入文件的字节)并且有一个有效的 HTTP响应,我正在测试它的浏览器说 ERR_INVALID_HTTP_RESPONSE 如果我已将文件附加到响应中。

最初我使用的是 HttpListener,但这要求我每次都以 运行 我的 IDE 作为管理员,所以我决定放弃它并开始使用 TcpListener

这只是一个简单的 Web 服务器,运行完全脱离 C# 并利用 System.Net 中的 TcpListener。到目前为止,我已经尝试使用 StreamWriter 中的 BaseStream 将文件的字节写入响应。

我一直在四处寻找其他通过 TCP/HTTP 发送文件的方法,但似乎有两件事很明显,它没有很好地记录如何正确地做到这一点,而且似乎没有人问过同样的问题对于这个特定场景。

到目前为止,处理传入连接响应的代码如下。

      StreamReader sr = new StreamReader(client.GetStream());
      StreamWriter sw = new StreamWriter(client.GetStream());
      string request = sr.ReadLine();
      if (request != null) {
        //byte[] testData = Encoding.UTF8.GetBytes("Test");
        string[] tokens = request.Split(" ");
        try {
          FileInfo file = files[tokens[1]];
          byte[] fileBytes = File.ReadAllBytes(file.FullName);
          sw.WriteLine("HTTP/1.0 200 OK\n");
          sw.BaseStream.Write(fileBytes, 0, fileBytes.Length);
          sw.Flush();
        } catch {
          sw.WriteLine("HTTP/1.0 404 OK\n");
          sw.Write("<h1>Error 404</h1><p>The file you were looking for does not exist</p>");
          sw.Flush();
        }
      }
      client.Close();

预期的结果是浏览器会像您从 imgur 中看到的那样显示图像 link,基本上与我将用于显示当前结果的屏幕截图的格式相同是预期的结果。

HTTP 规定初始行和 headers 应该以 CRLF 结尾(不是 LF),并且双 CRLF 应该将初始行和 headers 与响应 body.

分开

这里有一个 super-handy quick-guide 到 HTTP 协议:

https://www.jmarshall.com/easy/http/

在从 StreamWriter 操作切换到其基本流操作之前,您可能还需要刷新 StreamWriter

sw.Write("HTTP/1.0 200 OK\r\n\r\n");
sw.Flush(); //  <-- HERE
sw.BaseStream.Write(fileBytes, 0, fileBytes.Length);

我也会避免 WriteLine,因为不保证行结尾在所有平台上都相同。