Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Links to PDFs stored in DB 4

Status
Not open for further replies.

DatabaseDude

Programmer
Nov 7, 2005
112
US
I am in the process of writing code for uploading PDFs. The page will contain (1) upload control for adding new PDFs and (2) grid that lists current PDFs.

The table in which PDFs will be stored contains fields named AttachmentId (int), Attachment (varbinary(MAX)) and AttachmentFileName nvarchar(200).

The parts I understand:
- Uploading PDF
- Storing PDF in table
- Restricting uploads to PDF file type
- Populating grid to show names (AttachmentFileName) of PDFs

The part I'm not clear on:
- Creating a hyperlink that allows download of the PDF

I know how to accomplish this if the file is stored in a folder, but this is the first time I'm attempting to retrieve it from SQL instead.

Thanks so much in advance for your help!

 
I recommend an ashx handler for this. add an ashx to the project (getreport.ashx). and the code would look something like this
Code:
public bool isresuable{get{return false;}}

public void ProcessRequest(HttpContext context)
{
   int id = 0;
   if (int.TryParse(context.Request.QueryString["AttachmentId"], out id))
   {
      byte[] pdf = //select Attachment where AttachmentId = id;
      context.Response.Clear();
      context.Response.ContentType = "application/pdf";
      context.Response.AddHeader("Content-Disposition", "attachment;filename="[mydocument].pdf");
      context.Response.BinaryWrite(pdf);
      context.Response.Flush();
      context.Response.End();
   }
}
the url to the pdf report will be ~/getreport.ashx?AttachmentId=0

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Jason, That's a great idea to use a generic handler... I never think to use those and generally just write the response in the PageLoad Event of an aspx code file.

DatabaseDude, Jason is right about having to write the pdf data to the response object. I know it's probably a let down that you can't just use a hyperlink, but you have to run a query to extract the data from the DB and output that data to the response.


In case you need Jason's code in VB, here it is:
Code:
<%@ WebHandler Language="VB" Class="Handler" %>

Imports System
Imports System.Web

Public Class Handler : Implements IHttpHandler
    
    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        Dim id As Integer = 0
        If Integer.TryParse(context.Request.QueryString("AttachmentId"), id) Then
            Dim pdf As Byte() = 'select Attachment where AttachmentId = id
            context.Response.Clear()
            context.Response.ContentType = "application/pdf"
            context.Response.AddHeader("Content-Disposition", "attachment;filename=(mydocument).pdf")
            context.Response.BinaryWrite(pdf)
            context.Response.Flush()
            context.Response.End()
        End If
    End Sub
 
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

End Class

Senior Software Developer
 
Actually it sounds like a hyperlink is created (~/getreport.ashx?AttachmentId=0) ... and as long as the data can be viewed, it's all good :)

Thinking that if there were ever additional file types, the ashx file could be modified to include those, as well.

Thanks to Jason for the idea, and thank you for the VB.NET version!
 
yes any file type will work, just make sure the headers are correct. most online examples are used to load images from a db.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
jmeckley nailed the easiest way to do it. It's also noteworthy to mention that you have the option to create an IHttpHandler class and register it to handle the .pdf extension directly (an .ashx file is an IHttpHandler, it's just a simplified way of doing things).

This would enable you to use the URL "MyDocumentName.pdf" instead of "GetReport.ashx?AttachmentId=0" to accomplish the same means. The advantage of the former is that it's more readable and potentially better for search engines which may examine the URL to determine keywords.

If you want details on this alternate approach, let me know.

MCP, MCTS - .NET Framework 2.0 Web Applications
 
i would be interested in a pdf HttpHandler. I assume xls would be similar or part of the same Handler.

I've read about custom handlers but I haven't had a need for them yet. The most popular example I've seen is unhandled exceptions. although I'm not sure what the difference between that and Application_Error is.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
jmeckley,

It could handle .xls files if you'd like too, it depends on how it's implemented. Really, you'd do almost exactly what you did for the .ashx file, you'd typically just have a standalone IHttpHandler class.

Code:
namespace MyNamespace
{
    //NOTE: this doesn't need to be tied to an .ashx file.
    public class PdfHandler : IHttpHandler 
    {
        public bool IsReusable { get { return true; } }
        public void ProcessRequest(HttpContext context)
        {
            string[] urlSegments = context.Request.Url.Segments;

            //get the file name at the end of the URL
            string fileName = urlSegments[urlSegments.Length - 1];

            //get the file contents from the database based on the file name
            
            //write the file to the response stream as demostrated in previous post
        }
    }
}

Then you'd need to add this entry to the web.config file to map the .pdf extension to the HTTP handler.

Code:
<system.web>
	<httpHandlers>
		<add verb="*" path="*.pdf"
			type="MyNamespace.PdfHandler, MyAssembly" />
	</httpHandlers>
</system.web>

A request for a .pdf would thus come to your handler. Granted you'd probably want to tweak the system to be a little more robust (say by having the second to last segment of the URL be a username which you also pass to the database when requesting the file to avoid the need for unique file names), but you get the idea.

MCP, MCTS - .NET Framework 2.0 Web Applications
 
This would enable you to use the URL "MyDocumentName.pdf" instead of "GetReport.ashx?AttachmentId=0"


How to implement this? Please help me and show me step by step in doing this by using VB and c#. Thanks
 
use boulderbum's http handler (2 posts up) and my post (2nd post in the thread).

note: if you use a url like [tt]http://[domain]/myfile.pdf[/tt] then the file names must be unique. if they are not you must use some type of unique identifier to pull exactly 1 blob out of the database.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Yes. Note, however, that the unique identifier can be part of the URL structure apart from the QueryString. For instance, if a file is uniquely identified by a composite key consisting of two fields:

1. User Name
2. File Name

Then you can encoporate the composite key into the URL in a human-readable format.

For instance, if you wanted to access boulder_bum's document named "Sample.pdf", then you could use the URL:

Code:
[URL unfurl="true"]http://www.mysite.com/[/URL][b]boulder_bum[/b]/[b]Sample.pdf[/b]

...and parse out the "boulder_bum" and "Sample.pdf" before passing those parameters to the database. See the "URL segments" technique outlined in my previous post for detail.

MCP, MCTS - .NET Framework 2.0 Web Applications
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top