软件编程
位置:首页>> 软件编程>> C#编程>> C#如何自定义multipart/form-data的解析器

C#如何自定义multipart/form-data的解析器

作者:张云勇  发布时间:2023-12-04 18:59:03 

标签:C#,multipart,form-data,解析器

使用WebSocketSharp自定义实现Web服务时,无法解析multipart/form-data请求的数据。

通过查找资料,采用以下方式实现multipart/form-data的解析器。

解析辅助类 

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace YongFrame.Common.Utils
{
   /// <summary>
   /// multipart/form-data的解析器
   /// </summary>
   internal class HttpMultipartParser
   {
       /// <summary>
       /// 参数集合
       /// </summary>
       public IDictionary<string, string> Parameters = new Dictionary<string, string>();
       /// <summary>
       /// 上传文件部分参数
       /// </summary>
       public string FilePartName { get; }
       /// <summary>
       /// 是否解析成功
       /// </summary>
       public bool Success { get; private set; }
       /// <summary>
       /// 请求类型
       /// </summary>
       public string ContentType { get; private set; }
       /// <summary>
       /// 上传的文件名
       /// </summary>
       public string Filename { get; private set; }
       /// <summary>
       /// 上传的文件内容
       /// </summary>
       public byte[] FileContents { get; private set; }

/// <summary>
       /// 解析multipart/form-data格式的文件请求,默认编码为utf8
       /// </summary>
       /// <param name="stream"></param>
       /// <param name="filePartName"></param>
       public HttpMultipartParser(Stream stream, string filePartName)
       {
           FilePartName = filePartName;
           Parse(stream, Encoding.UTF8);
       }

/// <summary>
       /// 解析multipart/form-data格式的字符串
       /// </summary>
       /// <param name="content"></param>
       public HttpMultipartParser(string content)
       {
           var array = Encoding.UTF8.GetBytes(content);
           var stream = new MemoryStream(array);
           Parse(stream, Encoding.UTF8);
       }

/// <summary>
       /// 解析multipart/form-data格式的文件请求
       /// </summary>
       /// <param name="stream"></param>
       /// <param name="encoding">编码</param>
       /// <param name="filePartName"></param>
       public HttpMultipartParser(Stream stream, Encoding encoding, string filePartName)
       {
           FilePartName = filePartName;
           Parse(stream, encoding);
       }

private void Parse(Stream stream, Encoding encoding)
       {
           Success = false;

var data = ToByteArray(stream);

var content = encoding.GetString(data);

var delimiterEndIndex = content.IndexOf("\r\n", StringComparison.Ordinal);

if (delimiterEndIndex > -1)
           {
               var delimiter = content.Substring(0, content.IndexOf("\r\n", StringComparison.Ordinal)).Trim();

var sections = content.Split(new[] {delimiter}, StringSplitOptions.RemoveEmptyEntries);

foreach (var s in sections)
               {
                   if (s.Contains("Content-Disposition"))
                   {
                       var nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
                       var name = nameMatch.Value.Trim().ToLower();

if (name == FilePartName && !string.IsNullOrEmpty(FilePartName))
                       {
                           var re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
                           var contentTypeMatch = re.Match(content);

re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
                           var filenameMatch = re.Match(content);

if (contentTypeMatch.Success && filenameMatch.Success)
                           {
                               ContentType = contentTypeMatch.Value.Trim();
                               Filename = filenameMatch.Value.Trim();

var startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;

var delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
                               var endIndex = IndexOf(data, delimiterBytes, startIndex);

var contentLength = endIndex - startIndex;

var fileData = new byte[contentLength];

Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);

FileContents = fileData;
                           }
                       }
                       else if (!string.IsNullOrWhiteSpace(name))
                       {
                           var startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
                           Parameters.Add(name, s.Substring(startIndex).TrimEnd('\r', '\n').Trim());
                       }
                   }
               }

if (FileContents != null || Parameters.Count != 0)
               {
                   Success = true;
               }
           }
       }

public static int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)
       {
           var index = 0;
           var startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);

if (startPos != -1)
           {
               while (startPos + index < searchWithin.Length)
               {
                   if (searchWithin[startPos + index] == serachFor[index])
                   {
                       index++;
                       if (index == serachFor.Length)
                       {
                           return startPos;
                       }
                   }
                   else
                   {
                       startPos = Array.IndexOf(searchWithin, serachFor[0], startPos + index);
                       if (startPos == -1)
                       {
                           return -1;
                       }

index = 0;
                   }
               }
           }

return -1;
       }

public static byte[] ToByteArray(Stream stream)
       {
           var buffer = new byte[32768];
           using (var ms = new MemoryStream())
           {
               while (true)
               {
                   var read = stream.Read(buffer, 0, buffer.Length);
                   if (read <= 0)
                   {
                       return ms.ToArray();
                   }

ms.Write(buffer, 0, read);
               }
           }
       }
   }
}

调用示例

 HttpMultipartParser parser = new HttpMultipartParser(paramData);
            if (!parser.Success)
            {
                result.Code = -1;
                result.Message = "请求数据格式不能正确";
                return result;
            }
            if (!parser.Parameters.ContainsKey("optid") || parser.Parameters["optid"] == null || string.IsNullOrEmpty(parser.Parameters["optid"]))
            {
                result.Code = -1;
                result.Message = "用户名不能为空";
                return result;
            }
public void Upload(Stream stream)
{
    HttpMultipartParser parser = new HttpMultipartParser(stream, "image");
 
    if (parser.Success)
    {
        string user = HttpUtility.UrlDecode(parser.Parameters["user"]);
        string title = HttpUtility.UrlDecode(parser.Parameters["title"]);
 
        // Save the file somewhere
        File.WriteAllBytes(FILE_PATH + title + FILE_EXT, parser.FileContents);
    }
}
 

来源:https://blog.csdn.net/xiaoyong_net/article/details/107688427

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com