【问题标题】:Parsing Multipart files from Response Message C# .NET 4.8从响应消息 C# .NET 4.8 解析多部分文件
【发布时间】:2021-12-15 09:26:04
【问题描述】:

我的HttpClient 收到一个多部分响应(在HttpResponseMessage 对象中),我需要从响应中解析/读出文件。

要求是用.NET标准库(不高于.NET 4.8)解决。

以前我使用现在备受推崇的System.Net.Http.Formating 程序集或Microsoft.AspNet.WebApi.Client 程序集来执行此操作。像这样:

            List<byte[]> lbaFiles = new List<byte[]>();

            StreamContent strCont = new StreamContent(response.Content.ReadAsStreamAsync());
            strCont.Headers.Add("Content-Type", response.Content.Headers.ContentType);

            MultipartMemoryStreamProvider multipart = await strCont.ReadAsMultipartAsync();

            foreach (HttpContent cont in multipart.Contents)
            {
                byte[] baFile = await cont.ReadAsByteArrayAsync();
                lbaFiles.Add(baFile);
            } 

是否有任何其他 .NET 标准库(不高于 .NET 4.8)可以像上面的代码一样读取文件? 我只找到了MultipartContent,但是这个类只能创建一个MultipartForm 发送到Webserver。

非常感谢任何帮助。

【问题讨论】:

    标签: c# dotnet-httpclient multipart .net-4.8


    【解决方案1】:

    是的,您可以使用MimeKitLite 来执行此操作。

    使用 MimeKitLite v3.0 完成此任务的最简单方法如下所示:

    using (var contentStream = await response.Content.ReadAsStreamAsync ()) {
        var header = string.Format ("Content-Type:{0}\r\n\r\n", response.Content.Headers.ContentType);
        using (var headerStream = new MemoryStream (Encoding.UTF8.GetBytes (header), false)) {
            using (var chainedStream = new ChainedStream ()) {
                chained.Add (headerStream);
                chained.Add (contentStream);
    
                var reader = new MyMimeReader (chainedStream);
    
                await reader.ReadEntityAsync ();
            }
        }
    }
    

    MyMimeFilter.cs:

    public class MyMimeReader : MimeReader
    {
        static readonly byte[] EmptyInput = new byte[0];
        IMimeFilter _decoder;
        Stream _fileStream;
        string _fileName;
    
        public MyMimeReader (Stream stream) : base (stream, MimeFormat.Entity)
        {
        }
    
        protected override void OnHeadersBegin (long beginOffset, int beginLineNumber, CancellationToken cancellationToken)
        {
            // This marks the start of a new MIME entity, so reset our state.
            _decoder = DecoderFilter.Create (ContentEncoding.Default);
            _fileStream = null;
            _fileName = null;
        }
    
        protected override void OnHeaderRead (Header header, int beginLineNumber, CancellationToken cancellationToken)
        {
            switch (header.Id) {
            case HeaderId.ContentDisposition:
                // If the header is the Content-Disposition header, parse the
                // value to get the filename parameter value.
                if (ContentDisposition.TryParse (header.RawValue, out var disposition)) {
                    if (!string.IsNullOrEmpty (disposition.FileName)) {
                        // Make sure to only use the file name and not a full path.
                        _fileName = Path.GetFileName (disposition.FileName);
                    }
                }
                break;
            case HeaderId.ContentTransferEncoding:
                // If the header is the Content-Transfer-Encoding header,
                // parse the value so that we can decode the content.
                _decoder = DecoderFilter.Create (header.Value);
                break;
            }
        }
    
        protected override void OnMimePartBegin (ContentType contentType, long beginOffset, int beginLineNumber, CancellationToken cancellationToken)
        {
            // If there was a Content-Disposition header, then we'll use that filename.
            // Otherwise, check to see if there is a name parameter on the 
            // Content-Type header and use that. If all else fails, generate a
            // new filename.
            if (string.IsNullOrEmpty (_fileName)) {
                if (string.IsNullOrEmpty (contentType.Name)) {
                    // Generate a new filename.
                    _fileName = GenerateRandomFileName ();
                } else {
                    _fileName = Path.GetFileName (contentType.Name);
                }
            }
        }
    
        protected override void OnMimePartContentBegin (long beginOffset, int beginLineNumber, CancellationToken cancellationToken)
        {
            // Create the file stream that we'll save the content to.
            _fileStream = File.Create (_fileName);
        }
    
        protected override Task OnMimePartContentReadAsync (byte[] buffer, int startIndex, int count, CancellationToken cancellationToken)
        {
            int outputIndex, outputLength;
            byte[] decoded;
    
            decoded = _decoder.Filter (buffer, startIndex, count, out outputIndex, out outputLength);
    
            await _currentFileStream.WriteAsync (decoded, outputIndex, outputLength, cancellationToken);
        }
    
        protected override Task OnMimePartContentEndAsync (long beginOffset, int beginLineNumber, long endOffset, int lines, NewLineFormat? newLineFormat, CancellationToken cancellationToken)
        {
            int outputIndex, outputLength;
            byte[] decoded;
    
            decoded = _decoder.Flush (EmptyInput, 0, 0, out outputIndex, out outputLength);
    
            if (outputLength > 0)
                await _fileStream.WriteAsync (decoded, outputIndex, outputLength, cancellationToken);
    
            await _fileStream.FlushAsync (cancellationToken);
            _fileStream.Dispose ();
            _fileStream = null;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-20
      • 2014-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      相关资源
      最近更新 更多