Httplistener和文件上传

编程入门 行业动态 更新时间:2024-10-22 17:30:06
本文介绍了Httplistener和文件上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试从我的网络服务器检索上传的文件.当客户端通过网络表单(随机文件)发送其文件时,我需要解析请求以获取文件并进一步处理它.基本上,代码如下:

I am trying to retrieve an uploaded file from my webserver. As the client sends its files through a webform (random files), I need to parse the request to get the file out and to process it further on. Basically, the code goes as:

HttpListenerContext context = listener.GetContext(); HttpListenerRequest request = context.Request; StreamReader r = new StreamReader(request.InputStream, System.Text.Encoding.Default); // this is the retrieved file from streamreader string file = null; while ((line = r.ReadLine()) != null){ // i read the stream till i retrieve the filename // get the file data out and break the loop } // A byststream is created by converting the string, Byte[] bytes = request.ContentEncoding.GetBytes(file); MemoryStream mstream = new MemoryStream(bytes); // do the rest

因此,我能够检索文本文件,但对于所有其他文件,它们已损坏.有人能告诉我如何正确解析这些 HttplistnerRequests(或提供轻量级的替代方案)?

As a result, i am able to retrieve textfiles, but for all other files, they are corrupted. Could someone tell me how to parse these HttplistnerRequests properly (or providing a lightweighted alternative)?

推荐答案

我认为通过使用 HttpListener 而不是使用 ASP 的内置工具,您正在使事情变得比必要的更难.网.但是如果你必须这样做,这里有一些示例代码.注意:1) 我假设您在

上使用 enctype="multipart/form-data".2) 此代码旨在与仅包含您的 <input type="file"/> 的表单一起使用,如果您想发布其他字段或多个文件,您必须更改代码.3) 这只是一个概念/示例的证明,它可能有错误,而且不是特别灵活.

I think you are making things harder on yourself than necessary by doing this with an HttpListener rather than using the built in facilities of ASP.Net. But if you must do it this way here is some sample code. Note: 1) I'm assuming you're using enctype="multipart/form-data" on your <form>. 2) This code is designed to be used with a form containing only your <input type="file" /> if you want to post other fields or multiple files you'll have to change the code. 3) This is meant to be a proof of concept/example, it may have bugs, and is not particularly flexible.

static void Main(string[] args) { HttpListener listener = new HttpListener(); listener.Prefixes.Add("localhost:8080/ListenerTest/"); listener.Start(); HttpListenerContext context = listener.GetContext(); SaveFile(context.Request.ContentEncoding, GetBoundary(context.Request.ContentType), context.Request.InputStream); context.Response.StatusCode = 200; context.Response.ContentType = "text/html"; using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8)) writer.WriteLine("File Uploaded"); context.Response.Close(); listener.Stop(); } private static String GetBoundary(String ctype) { return "--" + ctype.Split(';')[1].Split('=')[1]; } private static void SaveFile(Encoding enc, String boundary, Stream input) { Byte[] boundaryBytes = enc.GetBytes(boundary); Int32 boundaryLen = boundaryBytes.Length; using (FileStream output = new FileStream("data", FileMode.Create, FileAccess.Write)) { Byte[] buffer = new Byte[1024]; Int32 len = input.Read(buffer, 0, 1024); Int32 startPos = -1; // Find start boundary while (true) { if (len == 0) { throw new Exception("Start Boundaray Not Found"); } startPos = IndexOf(buffer, len, boundaryBytes); if (startPos >= 0) { break; } else { Array.Copy(buffer, len - boundaryLen, buffer, 0, boundaryLen); len = input.Read(buffer, boundaryLen, 1024 - boundaryLen); } } // Skip four lines (Boundary, Content-Disposition, Content-Type, and a blank) for (Int32 i = 0; i < 4; i++) { while (true) { if (len == 0) { throw new Exception("Preamble not Found."); } startPos = Array.IndexOf(buffer, enc.GetBytes(" ")[0], startPos); if (startPos >= 0) { startPos++; break; } else { len = input.Read(buffer, 0, 1024); } } } Array.Copy(buffer, startPos, buffer, 0, len - startPos); len = len - startPos; while (true) { Int32 endPos = IndexOf(buffer, len, boundaryBytes); if (endPos >= 0) { if (endPos > 0) output.Write(buffer, 0, endPos-2); break; } else if (len <= boundaryLen) { throw new Exception("End Boundaray Not Found"); } else { output.Write(buffer, 0, len - boundaryLen); Array.Copy(buffer, len - boundaryLen, buffer, 0, boundaryLen); len = input.Read(buffer, boundaryLen, 1024 - boundaryLen) + boundaryLen; } } } } private static Int32 IndexOf(Byte[] buffer, Int32 len, Byte[] boundaryBytes) { for (Int32 i = 0; i <= len - boundaryBytes.Length; i++) { Boolean match = true; for (Int32 j = 0; j < boundaryBytes.Length && match; j++) { match = buffer[i + j] == boundaryBytes[j]; } if (match) { return i; } } return -1; }

为了帮助您更好地理解上述代码的作用,以下是 HTTP POST 的正文:

To help you better understand what the code above is doing, here is what the body of the HTTP POST looks like:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary9lcB0OZVXSqZLbmv ------WebKitFormBoundary9lcB0OZVXSqZLbmv Content-Disposition: form-data; name="my_file"; filename="Test.txt" Content-Type: text/plain Test ------WebKitFormBoundary9lcB0OZVXSqZLbmv--

我忽略了不相关的标题.如您所见,您需要通过扫描来解析正文以查找开始和结束边界序列,并删除文件内容之前的子标题.不幸的是,您不能使用 StreamReader,因为可能存在二进制数据.同样不幸的是,没有每个文件的 Content-Length(请求的 Content-Length 标头指定了正文的总长度,包括边界、子标头和间距.

I've left out the irrelevant headers. As you can see, you need to parse the body by scanning through to find the beginning and ending boundary sequences, and drop the sub headers that come before the content of your file. Unfortunately you cannot use StreamReader because of the potential for binary data. Also unfortunate is the fact that there is no per file Content-Length (the Content-Length header for the request specifies the total length of the body including boundaries, sub-headers, and spacing.

更多推荐

Httplistener和文件上传

本文发布于:2023-10-11 22:46:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1483053.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文件上传   Httplistener

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!