我正在使用 C# 中的 API 控制器,我的请求需要返回 IHttpActionResult
经过几个小时的研究,这是我的解决方案。
作为对我请求的回报,我正在使用来自 ApiController.cs 的 Content 方法:
protected internal FormattedContentResult<T> Content<T>(HttpStatusCode statusCode, T value, MediaTypeFormatter formatter);
我必须创建一个自定义 MediaTypeFormatter,它是:
class PdfMediaTypeFormatter : BufferedMediaTypeFormatter
{
private const string ContentType = "application/pdf";
private string FileName { get; set; }
public PdfMediaTypeFormatter(byte[] doc)
{
FileName = $"{DocumentsUtils.GetHeader(doc)}.pdf";
SupportedMediaTypes.Add(new MediaTypeHeaderValue(ContentType));
}
public override bool CanReadType(Type type)
{
return type.IsAssignableFrom(typeof(byte[]));
}
public override bool CanWriteType(Type type)
{
return type.IsAssignableFrom(typeof(byte[]));
}
public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
byte[] doc = (byte[])value;
using (Stream ms = new MemoryStream())
{
byte[] buffer = doc;
ms.Position = 0;
ms.Read(buffer, 0, buffer.Length);
writeStream.Write(buffer, 0, buffer.Length);
}
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
headers.ContentType = new MediaTypeHeaderValue(ContentType);
headers.ContentDisposition = new ContentDispositionHeaderValue("inline");
headers.ContentDisposition.FileName = FileName;
}
}
控制器中的方法如下所示:
public IHttpActionResult GetDownloadedDocument([FromUri] [FromUri] string IdDocument)
{
byte[] document = service.GetDoc(IdDocument);
return Content(HttpStatusCode.OK, document, new PdfMediaTypeFormatter(document));
}
为了解释,当 ApiController 必须返回一个 HttpRequest 时,它能够覆盖默认行为,正如您所看到的,您可以更改返回的流所写的内容,此外您还可以更改内容配置, 在这里设置文件名。
最后,在这个自定义 MediaTypeFormatter 的构造函数中,我使用静态 utils 类中的方法检索文档的标题,即:
public static string GetHeader(byte[] src)
{
if (src.Length > 0)
using (PdfReader reader = new PdfReader(src))
{
using (MemoryStream ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(reader, ms))
{
Dictionary<string, string> info = reader.Info;
if (!info.Keys.Contains("Title"))
return null;
else
return info["Title"];
}
}
}
else
return null;
}