Examples

Current Articles | Categories | Search

By Wayne Hamilton @ Friday, August 15, 2008 9:39 AM :: 177 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

Vote For It - Server Side Compiles in SQL CLR by Jonathan Kehayias

Greg Low a SQL Server MVP, has submitted a very compelling Connect item 265266, Add server-side compilation ability to SQL CLR which aims to remove the requirement to develop SQLCLR assemblies external to SQL Server.  Read about this suggestion here, and vote for it by visiting the Connect site to let Microsoft know you think it is important.

Using CLR Impersonation to Access Resources Outside of SQL Server by Jonathan Kehayias

Traditionally if you had a need to access a file or other resource outside of SQL Server, the SQL Server service account was required to have appropriate file system access to the folder or path containing the file.  With CLR integration, this is no longer an absolute requirement.  Identity Impersonation will allow you to implicitly or explicitly change the execution context inside of a SQLCLR Function, Procedure, or Trigger. 

Using an Application Configuration (app.config/web.config) File in SQL Server CLR Integration by Jonathan Kehayias

A common part of programming in .NET is to use an configuration file to store configuration information in an easily modifiable location.  The app.config or web.config file is an invaluable inclusion in most .NET projects and developers may need to maintain this functionality as a part of logic sharing between objects in the database and the application as well.  This article will demonstrate how to configure your SQLCLR project to use Configuration Files in SQL.

Recent Examples


Copyright 2007 by SQLCLR.net Terms Of Use Privacy Statement
Website graphics provided by Matt Green Designs
Page generated in 0.3437434 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.