简体   繁体   English

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

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

The issue I'm currently facing is that I'm unable to get my C# program to write the file I want to send in the response (I'm writing the bytes of the file) and have a valid HTTP response, the browser I'm testing it with is saying ERR_INVALID_HTTP_RESPONSE if I have appended the file to the response. 我目前面临的问题是,我无法让我的C#程序在响应中编写我想要发送的文件(我正在写文件的字节)并且有一个有效的HTTP响应,浏览器我如果我已经将文件附加到响应中,那么测试它就是说ERR_INVALID_HTTP_RESPONSE

Originally I was using a HttpListener but this was requiring me to run my IDE as admin every time so I decided to move away from it and start using a TcpListener . 最初我使用的是HttpListener,但这要求我每次都以管理员身份运行我的IDE,所以我决定放弃它并开始使用TcpListener

This is just a simple web server that is running entirely off of C# and utilizes the TcpListener from System.Net . 这只是一个完全由C#运行的简单Web服务器,它利用System.NetTcpListener So far I've tried using the BaseStream from the StreamWriter to write the bytes of the file into the response. 到目前为止,我已尝试使用StreamWriterBaseStream将文件的字节写入响应。

I have been searching around to look for other ways to send a file via TCP / HTTP however it seems two things are apparent, its not brilliantly documented on how to properly do it and nobody seems to have asked the same question for this specific scenario. 我一直在寻找其他方法通过TCP / HTTP发送文件,但似乎有两件事情是显而易见的,它没有出色地记录如何正确地做到这一点,似乎没有人为这个具体情况问过同样的问题。

So far the code that handles the response to the incoming connection is as follows. 到目前为止,处理传入连接响应的代码如下所示。

      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();

The expected result is that the browser will show the image much like you'd see from an imgur link, basically the same format as I will use to show the screenshot of the current result is the expected result. 预期的结果是浏览器将显示图像,就像您从imgur链接中看到的那样,基本上与我用于显示当前结果的屏幕截图的格式相同的格式是预期结果。

图片来自https://i.imgur.com/pxONnIP.png

HTTP dictates that initial lines and headers should end in CRLF ( not LF ), and that a double CRLF should separate initial lines and headers from the response body. HTTP规定初始行和标题应以CRLF而不是 LF )结尾,并且双CRLF应将初始行和标题与响应主体分开。

Here's a super-handy quick-guide to the HTTP protocol: 这是一个非常方便的HTTP协议快速指南:

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

You'll also probably need to flush your StreamWriter before you switch from operating over the StreamWriter to operating over it's base stream. 在从通过StreamWriter进行操作切换到通过其基本流进行操作之前,您可能还需要刷新StreamWriter

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

I'd also avoid WriteLine as the line endings are not guaranteed to be the same across all platforms. 我也避免使用WriteLine因为不保证所有平台的行结尾都是相同的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM