C#利用HttpListener实现接受上传文件

最近一个winform项目想直接用http协议与java端进行双向通讯,发现HttpListener可以实现http通讯,如果提交form的enctype=application/x-www-form-urlencoded则可以通过HttpUtility.ParseQueryString来解析HttpListenerRequest.InputStream中的内容,但如果是multipart/form-data,没有找到可以直接解析的类。
在网上找了半天,发现了http://www.xuebuyuan.com/464241.html,可以实现解析上传文件,不过处理一个1M的上传表单,竟然要8秒,性能实在无法接受(后来发现瓶颈主要在流读取和数组读取的速度差异)。
想着dotnet内部肯定有实现类,在用reflection反复查找后,终于确定HttpMultipartContentTemplateParser是可以用来解析MFC1867协议的,但由于是内部类无法在外部实现,故将代码整理如下。

/*
     RFC1867协议 举例     
     ------WebKitFormBoundaryKcbJOyftlttL1JBB
    Content-Disposition: form-data; name="name"

    zq
    ------WebKitFormBoundaryKcbJOyftlttL1JBB
    Content-Disposition: form-data; name="myfile"; filename="IMG_20130219_181308.jpg"
    Content-Type: image/jpeg
    [二进制数据]

    ------WebKitFormBoundaryKcbJOyftlttL1JBB--
     */

    /// <summary>
    /// 解析RFC1867协议
    /// </summary>
    public class HttpMultipartFormParser {
        private string boundary;
        private byte[] _boundary;
        private byte[] _data;
        private int _length;
        private int _lineLength = -1;
        private int _lineStart = -1;
        private int _pos;
        private bool _lastBoundaryFound;
        private string _partContentType;
        private int _partDataLength = -1;
        private int _partDataStart = -1;
        private string _partFilename;
        private string _partName;
        private Encoding _encoding;

        public HttpMultipartFormParser(HttpListenerRequest request, Encoding encoding) {
            this._encoding = encoding;
            //Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
            Regex regex = new Regex("boundary=(.*)$");

            Match match = regex.Match(request.ContentType);

            if (match.Success) {
                boundary = match.Groups[1].Value;
                _boundary = _encoding.GetBytes("--" + boundary);
            }

            Stream input = request.InputStream;

            //将上传文件保存到内存
            BufferedStream br = new BufferedStream(input);

            MemoryStream ms = new MemoryStream();

            
要使用C# HttpListener接收Unity上传的视频,可以使用以下步骤: 1. 在Unity中编写脚本,将视频文件转换为字节数组并将其发送到指定的URL。 ```csharp using UnityEngine; using System.IO; using System.Net; public class VideoUploader : MonoBehaviour { public string url; public string filePath; void Start() { byte[] videoBytes = File.ReadAllBytes(filePath); StartCoroutine(UploadVideo(videoBytes)); } IEnumerator UploadVideo(byte[] videoBytes) { UnityWebRequest request = UnityWebRequest.Put(url, videoBytes); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { Debug.Log("Video uploaded successfully!"); } else { Debug.Log("Video upload failed: " + request.error); } } } ``` 2. 在C#中编写HttpListener服务器,以侦听从Unity发送的请求。在服务器代码中,使用`HttpListenerContext`对象从请求中获取视频数据并将其保存到本地文件中。 ```csharp using System; using System.IO; using System.Net; public class HttpServer { private HttpListener listener; private string savePath; public HttpServer(string prefix, string savePath) { listener = new HttpListener(); listener.Prefixes.Add(prefix); this.savePath = savePath; } public void Start() { listener.Start(); Console.WriteLine("Server started."); while (true) { HttpListenerContext context = listener.GetContext(); ProcessRequest(context); } } private void ProcessRequest(HttpListenerContext context) { HttpListenerRequest request = context.Request; HttpListenerResponse response = context.Response; if (request.HttpMethod == "PUT") { byte[] videoBytes = new byte[request.ContentLength64]; int bytesRead = request.InputStream.Read(videoBytes, 0, videoBytes.Length); if (bytesRead > 0) { string fileName = Path.GetFileName(request.Url.LocalPath); string filePath = Path.Combine(savePath, fileName); File.WriteAllBytes(filePath, videoBytes); response.StatusCode = 200; response.StatusDescription = "OK"; response.OutputStream.Close(); Console.WriteLine("Video saved to: " + filePath); } } } public void Stop() { listener.Stop(); listener.Close(); Console.WriteLine("Server stopped."); } } ``` 3. 在Main函数中实例化HttpServer并启动它。 ```csharp static void Main(string[] args) { string prefix = "http://localhost:8080/"; string savePath = "C:\\Videos"; HttpServer server = new HttpServer(prefix, savePath); server.Start(); Console.ReadKey(); server.Stop(); } ``` 上述代码中,`prefix`是HTTP监听器的前缀,`savePath`是要保存视频文件的本地路径。在Unity中将`url`设置为服务器的`prefix`和视频文件名即可上传视频文件。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值