如何在C#Web API中将pdf异步存储到IFrame?
我有个问题。目前,我在Web Api控制器中的代码将HttpResponseMessage发送回浏览器,如下所示:如何在C#Web API中将pdf异步存储到IFrame?,c#,pdf,iframe,asynchronous,C#,Pdf,Iframe,Asynchronous,我有个问题。目前,我在Web Api控制器中的代码将HttpResponseMessage发送回浏览器,如下所示: var response = new HttpResponseMessage(HttpStatusCode.OK); MemoryStream stream = ConvertWordToPdf(document.Path); response.Content = new ByteArrayContent(stream.GetBuffer()); response.Cont
var response = new HttpResponseMessage(HttpStatusCode.OK);
MemoryStream stream = ConvertWordToPdf(document.Path);
response.Content = new ByteArrayContent(stream.GetBuffer());
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = stream.GetBuffer().Length;
return response;
public MemoryStream ConvertWordToPdf(string id)
{
var wordFilename = id;
var reds = new RichEditDocumentServer();
reds.LoadDocument(wordFilename, DevExpress.XtraRichEdit.DocumentFormat.OpenXml);
var ms = new MemoryStream();
reds.ExportToPdf(ms);
return ms;
}
但是,为了提高性能,我希望使用流式或异步方法(与此不同)。因此,与其等待所有字节加载到内存中,然后将它们流式传输到客户端,我希望在转换后加载http响应时开始将其流式传输到客户端
所以,我使用的是一个没有物理文件的内存流(这没关系吧?)。我尝试使用StreamContent和PushStreamContent,但无法使其正常工作。我可以让它下载的文件作为附件,我不想。它需要在IFrame中进行更新,就像非异步的一样:
< iframe src="{{url}}" type="application/pdf" width="100%" height="660px"/>
编辑
为了澄清,将上面的响应片段更改为以下内容不会产生任何明显的性能差异,也不会对异步等效项产生任何影响:
var response = new HttpResponseMessage(HttpStatusCode.OK);
var stream = ConvertWordToPdf(document.Path);
var bytes = stream.ToArray();
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = bytes.Length;
return response;
预期以下内容将作为异步工作,但pdf不会在IFrame中显示内容:
var response = new HttpResponseMessage(HttpStatusCode.OK);
var stream = ConvertWordToPdf(document.Path);
var bytes = stream.ToArray();
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = bytes.Length;
return response;
此外,用ContentType替换以下内容会导致在IFrame之外下载文档,这不是本练习的目的:
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
请特别考虑您当前代码的这一行:
response.Content.Headers.ContentLength = stream.GetBuffer().Length;
使用创建的PDF大小设置标题行(即,在开始发送实际PDF之前要发送的行)
在完成生成PDF之前,您不知道确切的大小
因此,只要您想设置此标题,就不能在完全生成PDF之前开始发送它
关于stackoverflow的几个问题表明,至少某些浏览器版本需要ContentLength
标题才能正常工作
因此,你无法实现你的目标
另外,返回
stream.GetBuffer()
(并相应地将上面的大小设置为stream.GetBuffer().Length
)。但这是错误的。请查看msdn页面上的备注:
请注意,缓冲区包含可能未使用的已分配字节。例如,如果字符串“test”被写入MemoryStream
对象,则从GetBuffer
返回的缓冲区长度是256,而不是4,其中有252个字节未使用。要仅获取缓冲区中的数据,请使用ToArray
方法;但是,ToArray
会在内存中创建数据的副本
因此,在您的情况下,可能会在PDF中附加几个尾随的垃圾字节
因此,您应该改为使用
ToArray
或(将资源考虑在内,参见引用的最后一句)传输方法,这些方法只处理字节[]
的一部分,并将它们限制为流的第一个流。长度字节流。GetBuffer()
请特别考虑您当前代码的这一行:
response.Content.Headers.ContentLength = stream.GetBuffer().Length;
使用创建的PDF大小设置标题行(即,在开始发送实际PDF之前要发送的行)
在完成生成PDF之前,您不知道确切的大小
因此,只要您想设置此标题,就不能在完全生成PDF之前开始发送它
关于stackoverflow的几个问题表明,至少某些浏览器版本需要ContentLength
标题才能正常工作
因此,你无法实现你的目标
另外,返回stream.GetBuffer()
(并相应地将上面的大小设置为stream.GetBuffer().Length
)。但这是错误的。请查看msdn页面上的备注:
请注意,缓冲区包含可能未使用的已分配字节。例如,如果字符串“test”被写入MemoryStream
对象,则从GetBuffer
返回的缓冲区长度是256,而不是4,其中有252个字节未使用。要仅获取缓冲区中的数据,请使用ToArray
方法;但是,ToArray
会在内存中创建数据的副本
因此,在您的情况下,可能会在PDF中附加几个尾随的垃圾字节
因此,您应该改为使用ToArray
或(将资源考虑在内,参见引用的最后一句)传输方法,这些方法只处理字节[]
的一部分,并将它们限制为流的第一个流。长度字节流。GetBuffer()
您是否认为pdf将以增量方式显示?只有当Pdf是为其设计的(快速Web视图或线性化Pdf)时,这才有效。是的,增量;我该怎么做?你是否认为pdf将以增量方式显示?只有当Pdf是为其设计的(快速Web视图或线性化Pdf)时,这才有效。是的,增量;我该怎么做呢?即使ToArray()已经足够了,您所建议的异步方式又如何呢?正如问题中所指出的,我包含的代码片段显然是同步的。你没有回答这个问题。我确实回答了同步对你没有改善的问题。在发送ContentLength
标题之前,无法开始传输。对于该标题,您需要实际的PDF大小。在完全创建PDF之前,您不知道大小。因此,无论如何都必须缓存。因此,通过使事情异步,你会使事情变得更慢。另一方面,如果你决定不再需要ContentLength
头,那么异步将是一种改进。@Carnotaurus因此,您是否需要
ContentLength`标题?我似乎至少需要它,以便它在iframe中呈现,即使ToArray()足够了,您建议的是异步的吗?正如问题中所指出的,我包含的代码片段显然是同步的。你没有回答这个问题。我确实回答了同步不存在的问题