c# - 如何从 MIME 内容创建图像?
问题描述
我正在尝试在C#
.NET Core 2.2 框架之上编写一个小型控制台应用程序。
控制台应用程序将向外部 API 发出 HTTP 请求以获取多个图像。我能够向服务器发出请求并获得响应。但是,服务器使用 MIMI 消息以多部分响应进行响应。
我能够解析请求并获取每条消息的 MIME 正文。但是,我无法弄清楚如何从正文内容中创建文件。
我尝试将正文作为字符串写入文件,但它不起作用
string body = GetMimeBody(message);
File.WriteAllText("image_from_string" + MimeTypeMap.GetExtension(contentType), bytes);
我也尝试将字符串转换为byte[]
like 但仍然无法正常工作
byte[] bytes = Encoding.ASCII.GetBytes(body);
File.WriteAllBytes("image_from_ascii_bytes" + MimeTypeMap.GetExtension(contentType), bytes);
byte[] bytes = Encoding.Default.GetBytes(body);
File.WriteAllBytes("image_from_default_bytes" + MimeTypeMap.GetExtension(contentType), bytes);
byte[] bytes = Encoding.UTF8.GetBytes(body);
File.WriteAllBytes("image_from_utf8_bytes" + MimeTypeMap.GetExtension(contentType), bytes);
“不工作”是指图像无法正确打开。照片查看器说“图像似乎已损坏或损坏”。
我怎样才能正确地从消息中制作出好的图像?
更新
这是代码以及解析部分
var responseContentType = response.Content.Headers.GetValues("Content-Type").FirstOrDefault();
string splitter = string.Format("--{0}", GetBoundary(responseContentType));
string content = await response.Content.ReadAsStringAsync();
var messages = content.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
foreach (var message in messages)
{
var mimiParts = message.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
if (mimiParts.Length == 0)
{
continue;
}
string contentId = Str.GetValue("Content-ID", mimiParts, ':');
string objectId = Str.GetValue("Object-ID", mimiParts, ':');
string contentType = Str.GetValue("Content-Type", mimiParts, ':');
if (string.IsNullOrWhiteSpace(contentId) || string.IsNullOrWhiteSpace(objectId) || string.IsNullOrWhiteSpace(contentType))
{
continue;
}
string body = mimiParts[mimiParts.Length - 1];
var filename = string.Format("{0}_{1}{2}", contentId, objectId, MimeTypeMap.GetExtension(contentType));
var decoded = System.Net.WebUtility.HtmlDecode(data);
File.WriteAllText("image_from_html_decoded_bytes" + filename, decoded);
}
这是解析消息的方法
public class Str
{
public static string GetValue(string startWith, string[] lines, char splitter = '=')
{
foreach (var line in lines)
{
var value = line.Trim();
if (!value.StartsWith(startWith, StringComparison.CurrentCultureIgnoreCase) || !line.Contains(splitter))
{
continue;
}
return value.Split(splitter)[1].Trim();
}
return string.Empty;
}
}
更新 2
根据下面的反馈,我尝试使用MimeKit包而不是尝试自己解析响应。以下是我尝试使用响应的方式。但是,我仍然遇到与上述相同的错误。写入图像文件时,出现图像损坏错误。
var responseContentType = response.Content.Headers.GetValues("Content-Type").FirstOrDefault();
if (!ContentType.TryParse(responseContentType, out ContentType documentContentType))
{
return;
}
var stream = await response.Content.ReadAsStreamAsync();
MimeEntity entity = MimeEntity.Load(documentContentType, stream);
Multipart messages = entity as Multipart;
if (messages == null)
{
throw new Exception("Unable to cast entity to Multipart");
}
foreach (MimeEntity message in messages)
{
string contentId = message.Headers["Content-ID"];
string objectId = message.Headers["Object-ID"];
string contentType = message.Headers["Content-Type"];
if (string.IsNullOrWhiteSpace(contentId) || string.IsNullOrWhiteSpace(objectId) || string.IsNullOrWhiteSpace(contentType))
{
continue;
}
var filename = string.Format("{0}_{1}{2}", contentId, objectId, MimeTypeMap.GetExtension(contentType));
message.WriteTo(filename);
}
解决方案
MimeEntity.WriteTo (file)
不幸的是,将包含导致损坏错误的 MIME 标头。
您需要做的是将 MimeEntity 转换为 MimePart,然后使用以下命令保存解码的内容MimePart.Content.DecodeTo (stream)
:
var responseContentType = response.Content.Headers.GetValues("Content-Type").FirstOrDefault();
if (!ContentType.TryParse(responseContentType, out ContentType documentContentType))
{
return;
}
var stream = await response.Content.ReadAsStreamAsync();
MimeEntity entity = MimeEntity.Load(documentContentType, stream);
Multipart multipart = entity as Multipart;
if (multipart == null)
{
throw new Exception("Unable to cast entity to Multipart");
}
foreach (MimePart part in multipart.OfType<MimePart> ())
{
string contentType = part.ContentType.MimeType;
string contentId = part.ContentId;
string objectId = part.Headers["Object-ID"];
if (string.IsNullOrWhiteSpace(contentId) || string.IsNullOrWhiteSpace(objectId) || string.IsNullOrWhiteSpace(contentType))
{
continue;
}
var filename = string.Format("{0}_{1}{2}", contentId, objectId, MimeTypeMap.GetExtension(contentType));
using (var output = File.Create (filename))
part.Content.DecodeTo (output);
}
推荐阅读
- javascript - 柴在浅层平等断言上失败了
- c++ - 如何通过指针访问数组的元素?
- prolog - 使用 clpfd 的问题空间很小,超出了 SWI-Prolog 堆栈限制
- scala - 更简洁地从 spark 数据框中选择多列
- typescript - strictNullChecks 导致错误:泛型类型不存在 hasOwnProperty
- mongodb - 动态访问MongoDB字段
- android - Android:在我的应用程序中实现 Trusted Place API
- angular - 如何从 Angular2 中的 XHR 标头获取日期?
- laravel - 无法使用vue axios在数据表中显示数据
- android - 如何将用户重定向到定义的 Play 商店实验变体?