简体   繁体   English

如何在不保存ASP.NET MVC PDF文件的情况下将其流化到临时文件夹位置?

[英]How can I do ASP.NET MVC PDF file Streaming without saving it in the temp folder location?

I'm able to stream a PDF at a remote URI using the below code: 我可以使用以下代码在远程URI上传输PDF:

    public ActionResult LoadPdfStream(string url)
    {
        // this gets me the memory stream from the PDF file
        MemoryStream memBuffer = _pdfViewerLogic.ConvertPdfToStream(url);

        byte[] bytes = memBuffer.GetBuffer();

        Response.ClearContent();
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "inline");
        Response.AddHeader("Content-Length", bytes.Length.ToString());
        foreach(byte b in bytes)
        { Response.OutputStream.WriteByte(b); }

        Response.Flush();
        Response.Clear();
        Response.Close();

        HttpContext.ApplicationInstance.CompleteRequest();

        return Content("");
    }

It creates a PDF file starting with a name of 'LoadPdfStream' at the temp inet location. 它会在临时inet位置创建一个以'LoadPdfStream'开头的PDF文件。 How can I prevent it from creating a temp file. 如何防止它创建临时文件。 I just want to stream the PDF content on the browser window without having the app to save it as a temp file. 我只想在浏览器窗口中流式传输PDF内容,而无需应用程序将其另存为临时文件。

Thanks in advance!!! 提前致谢!!!

Looks like this has nothing to do with MVC at all. 看起来这与MVC完全无关。 It must your component/code converting PDF that creates temp file. 它必须将您的组件/代码转换为PDF才能创建临时文件。 Try to remove any response writing logic or just step with debug and stop it after ConvertPdfToStream() call and I'm pretty sure you'll still see file created already. 尝试删除任何响应编写逻辑,或者仅执行调试步骤,然后在ConvertPdfToStream()调用之后将其停止,我敢肯定,您仍然会看到已经创建的文件。

But much better would be rewriting your code to work better with MVC architecture. 但是更好的办法是重写代码,使其与MVC架构更好地配合使用。 Now you: 1. Explicitly set response data 2. Flush the response stream, close the response 3. And still return the new Content("") object to be handled by MVC routine. 现在您:1.明确设置响应数据2.刷新响应流,关闭响应3.并仍返回要由MVC例程处理的新Content(“”)对象。 That`s weird and pretty unpredictable. 那很奇怪,而且几乎不可预测。 In our WebApi (near same as MVC) project we're using something like this to send files (simplified and modified hardly to match your sample): 在我们的WebApi(与MVC几乎相同)项目中,我们正在使用类似的方式来发送文件(经过简化和修改的方式很难与您的示例匹配):

/// <summary>
/// Custom <see cref="IHttpActionResult"/> that sends files using <see cref="StreamContent"/>
/// </summary>
public class FileResult : IHttpActionResult
{
    ILogger Log = LogManager.GetLogger();

    /// <summary>
    /// Write buffer size. We use it for our internal services so 8MB buffer size - is the size tested and approved to be fine for our 1Gbps LAN transfers ;) you might want to change it
    /// </summary>
    private const int BUFFER_SIZE = 8388608;

    /// <summary>
    /// Initializer
    /// </summary>
    /// <param name="data">File data</param>
    public FileResult(byte[] data)
    {
        Data = data;
    }

    /// <summary>
    /// File data
    /// </summary>
    public byte[] Data
    { get; private set; }


    /// <inheritdoc cref="IHttpActionResult.ExecuteAsync(CancellationToken)"/>
    public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {

        var response = new HttpResponseMessage();
        response.Content = new PushStreamContent(async (responseStream, content, context) =>
            {
                using (var source = new MemoryStream(Data))
                {
                    try
                    {
                        if (source != null)
                            await source.CopyToAsync(responseStream, BUFFER_SIZE, cancellationToken);
                    }
                    catch (Exception e)
                    {
                        if (cancellationToken.IsCancellationRequested)
                            Log.Info("Data stream read operation aborted by client.");
                        else
                        {
                            Log.Warn(e);
                            throw;
                        }
                    }
                    responseStream.Close();
                }
            },
            new MediaTypeHeaderValue("application/pdf"));

        response.Content.Headers.ContentLength = Data.Length;
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "file.pdf",
            Size = Data.Length,
        };

        return response;
    }
}

and then use it in you controller like this: 然后像这样在控制器中使用它:

public IHttpActionResult LoadPdfStream(string url)
{
    // this gets me the memory stream from the PDF file
    MemoryStream memBuffer = _pdfViewerLogic.ConvertPdfToStream(url);

    byte[] bytes = memBuffer.GetBuffer();

    return new FileResult(bytes);
}

This way you don`t need to take care about response flush and manually force request end. 这样,您就不必担心响应刷新并手动强制请求结束。 Also this streaming code is called only in case if client really waits for it and cancelled nicely on client stream close/request abort. 此外,仅在客户端真正等待并在客户端流关闭/请求中止时很好地取消的情况下才调用此流代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM