开发者

Displaying pdf files in a web page from a sql database directly without needing to save them to the server file system

开发者 https://www.devze.com 2023-04-12 11:18 出处:网络
I\'m currently using an html embed tag to display a pdf file that is saved on the local server.开发者_StackOverflowIs there a wayo to display a pdf file on my page without having to save it to the loc

I'm currently using an html embed tag to display a pdf file that is saved on the local server.开发者_StackOverflow Is there a wayo to display a pdf file on my page without having to save it to the local file system of the server? I just wand to pass it to the view from the controller in such a way that it can be displayed as a pdf in the page without having it stored on the file system directly.

Alternatively, is there a way to call a method to delete the pdf file from the server once the user has navigated away from the page they are viewing? How do I tell if th euser has navicated away from the page and how do i cause that to trigger a method that will delete the file?


I created a MVC class called PdfResult that returns a byte array as a PDF file.

The purpose is as follows (can't upload the source code, sorry):

  1. PdfResult inherits from FileStreamResult
  2. Set the Content-Type header to application/pdf
  3. Set the Content-Disposition to either attachment or inline, and set an appropriate file name
  4. Convert your data to a Stream -- if your data is a byte array, then write it to a MemoryStream.

See https://stackoverflow.com/a/16673120/272072 for a good example of how to do this.

Then, your embed code just needs to point to the action method, as if it was a PDF file.
Here's an example:

public ActionResult ShowPdf() {
    // Note: the view should contain a tag like <embed src='MyController/GetPdf'>
    return View(); 
}

public ActionResult GetPdf() {
    byte[] pdfBytes = dataRepo.GetPdf(...);
    return new PdfResult(pdfBytes, "Filename.pdf", false) ;
} 


Here is a link to a CodeProject article and code sample titled Download and Upload Images from SQL Server via ASP.NET MVC. This gives an example of an efficient method to stream content to and from SQL Server via MVC.

You can easily adapt the code to stream your PDF file downloads.

UPDATE

The article uses a DataReader, but it can easily be adapted to Linq2Sql or EF. As an example, here is the Read method where I am reading from the database and copying to the stream:

public override int Read(byte[] buffer, int offset, int count)
{
    result = _attachments.ExecuteStoreQuery<byte[]>(
             "SELECT SUBSTRING(AttachmentBytes, " + position.ToString() +
             ", " + count.ToString() + ") FROM Attachments WHERE Id = {0}",
             id).First();

    var bytesRead = result.Length;
    Buffer.BlockCopy(result, 0, buffer, 0, bytesRead);

    position += bytesRead;
    return (int)bytesRead;
}


You can read the PDF as a bytestream from the database and save it to the http response stream. If you have set the content type correctly to application/pdf, then the browser will load the document in the PDF plugin.

Update (14/Oct/2011): You need to write the bytestream to the Response.OutputStream object. How you create and write the byte stream is dependent on how you have stored in the database and how you are retrieving it. The following code snippet is from an article we have on our website - Generate PDF Forms In ASP.NET Using PDFOne .NET v3.

  // Get the page's output stream ready
  Response.Clear();
  Response.BufferOutput = true;
  // Make the browser display the forms document
  // using a PDF plug-in. (If no plug in is available, 
  // the browser will show the File -> Save As dialog box.
  Response.ContentType = "application/pdf"; 

  // Write the forms document to the browser
  doc.Save(Response.OutputStream);

  doc.Close();
  doc.Dispose();

The doc object is from our component. You need not use that. This code snippet is only for your understanding. For your requirement, you may have to something like bytestream.save(Response.OutputStream) I guess. BTW, this code is for ordinary ASP.NET, not MVC.

DISCLAIMER: I work for Gnostice.


If you want to create the PDF 100% dynamically, you would generate it completely in memory then stream it out directly to the requesting web browser without saving it as a file. This is very easy to do with the right tools. I would recommend AspPDF from Persits.com as a way to do this very easily. Take a look at their online documentation to see how simple this is to do without creating a bunch of rendered PDF files all over your server.

If you cannot do something like that, then simply incorporate a process to cleanup your "expired" PDF files from your server's filesystem based on their age. For example, after you have created your local PDF file, you just look through the folder containing your temporary PDF's and delete any you find over a certain age. You cannot reliably tell if or when a user has navigated away from your page or site.


For the first part of your question, like mentioned in the comments, use some type of stream object to pass the PDF data around. Right now, you are streaming the file to the local file system, then streaming it once again to the embedded tag for display. Just do away with the intermediate step of saving to the file system, and do the whole thing in memory (although, that's not really a model of efficiency, and might not scale well).

Regarding the second part of your question, that's not as straightforward. MVC really has no concept of state (viewstate, etc.), so it doesn't have events that can be fired from a state change (say, navigating away from a page).

You could use Javascript to detect a user navigating away from your page (windows.onunload), that calls a (C#/VB) method to remove the file from the file system. You would probably have to use AJAX to communicate back to the server, using an HTTP POST method, and have something listening at that URL endpoint to fire your method that removes the file.

0

精彩评论

暂无评论...
验证码 换一张
取 消