Examples

Current Articles | Categories | Search

By Wayne Hamilton @ Friday, August 15, 2008 9:39 AM :: 1507 Views :: 0 Comments

In many corporate environments, like mine, there is often a reason to separate your web servers onto a separate network that is outside a FireWall separating them from the rest of your Servers.  Often Security teams are very reluctant to open up any extra ports to the "inside world" than are absolutely necessary.  Obviously SQL Server is a vital part of most web applications, so a method of communication between the Web Server and SQL Server is set up.

On one of our applications we have give the users the ability to store files as attachments to records that are kept in a database.  The downside was that the admin tools are on the intranet, but the end result needs to be available to the internet web site.  I've never been a fan of storing Files in a database, so I began looking for a way to keep the images in a single location that was protected and hopefully on the file system.

Since the outside world can see the database, I decided to stream the files out through the port that was already open using CLR.  The only thing we needed to set up was access for the SQL Server Service account to the share where the files (in our case .pdfs) were stored.  Now I needed to set up a Function to call, and a ASP.NET page to call it.

The function turned out to be very short.  Just a single line and an extra import from the Visual Studio Template.  Obviously I can add some error handling, but I'll leave that as a further exercise. :)  When you create the function in SQL there are two things that you need to double check.  First, this procedure must run with EXTERNAL ACCESS permissions and the function should be created with a return type of varbinary(max).  The SQL default uses varbinary(8000) which will throw errors on larger files.

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports system.io

Partial Public Class UserDefinedFunctions
  <Microsoft.SqlServer.Server.SqlFunction()> _
  Public Shared Function ReadFile(ByVal fname As SqlString) As SqlBinary
    ' Add your code here
    Return New SqlBinary(File.ReadAllBytes(fname.ToString()))
  End Function
End Class

The actual "meat" of the ASP.NET page ended up being just about as short.  Generally I'd use a Code Behind page, but for this example, the <script> tags are just as easy.  This page can be extended to check permissions using Windows Authentication, a Session Variable, or do a number of other things.  My version just serves up the file.  If you server more files types than .PDFs remember that you'll also need to change the content type in the page.  The code for showing the "Save As..." dialog box is also in here, but commented out.  The current code will display the file in the browser.

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SQLClient" %>

<script runat="server">
  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
   
'Prompt File Download
    'Response.AddHeader("content-disposition", "attachment; filename=fname.pdf")

    'Display in Browser with appropriate MIME Handler
    Response.ContentType = "application/pdf"
    Response.AddHeader("content-disposition", "inline; filename=fname.pdf")

    'Create your Connection and Command Objects   
    Dim conn As New SqlConnection("YourConnectionString")
    Dim cmd As New SqlCommand(String.Format("SELECT dbo.ReadFile ({0}')", YourFileName), conn)

    conn.Open()

    'Stream the contents of the File to the Browser
    Response.BinaryWrite(cmd.ExecuteScalar())
    conn.Close()

    'End the Response so the browser knows the entire file is there.
    Response.End()
  End Sub
</script>

About all you need to do is determine how to choose which file needs to be included.  Sometimes that means sending an ID to SQL and looking up the file name, and other times you'll want to pass in an file name directly.  Hopefully this will provide a relatively simple method for serving up content protected by a firewall on the internet.

Posted @ Friday, August 15, 2008 9:39 AM by Wayne Hamilton
Previous Page | Next Page
Comments
Currently, there are no comments. Be the first to post one!
You must be logged in to post a comment. You can login here

Survey

Which of the following CLR objects are you currently using in SQL Server?




Submit Survey  View Results

Links

  Search

What's New

 Subscribe in a reader

Q&A with Adam Machanic - Who's Afraid of SQLCLR by Jonathan Kehayias

You could almost hear the gasps of horror when Microsoft integrated the .NET Common Language Runtime (CLR) into SQL Server 2005. Run C# or VB.NET code inside SQL Server? For many database developers and administrators, it was like an alien had just burst through SQL Server’s midsection.

But SQL Server MVP Adam Machanic says that more and more developers and DBAs are discovering that far from destroying SQL Server performance and security, SQLCLR is actually a powerful ally in solving complex business and technical problems.

Read More on the PASS website..

SQLCLR String Splitting Part 2: Even Faster, Even More Scalable by Site Administrator

SQL Server MVP Adam Machanic shows a new way of parsing strings in SQL Server using SQLCLR that outperforms all conventional TSQL methods, as well as the most common SQLCLR implemenations, using a custom split function that allows streaming of the results.

Trading in xp_cmdshell for SQLCLR (Part 1) - List Directory Contents by Jonathan Kehayias

Learn how to use SQLCLR to get file system information instead of using xp_cmdshell on your SQL Servers.

Recent Examples


Copyright 2007 by SQLCLR.net Terms Of Use Privacy Statement
Website graphics provided by Matt Green Designs
Page generated in 0.218407 seconds.

All information and example code on this site is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from its use.

This site is in no way affiliated with Microsoft. Unless specifically stated otherwise, nothing should be construed to represent the official positions or opinions of Microsoft and/or its Employees.