如何在C#Web API中将pdf异步存储到IFrame?

如何在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

我有个问题。目前,我在Web Api控制器中的代码将HttpResponseMessage发送回浏览器,如下所示:

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()足够了,您建议的是异步的吗?正如问题中所指出的,我包含的代码片段显然是同步的。你没有回答这个问题。我确实回答了同步不存在的问题