从响应消息 C# .NET 4.8 解析多部分文件
Posted
技术标签:
【中文标题】从响应消息 C# .NET 4.8 解析多部分文件【英文标题】:Parsing Multipart files from Response Message 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。
非常感谢任何帮助。
【问题讨论】:
【参考方案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;
【讨论】:
以上是关于从响应消息 C# .NET 4.8 解析多部分文件的主要内容,如果未能解决你的问题,请参考以下文章