Wednesday, October 17, 2012

Save Files to SQL Server Database using FileUpload Control

I have already explained how to save and retrieve files in SQL Server database using ASP.Net in my article Save and Retrieve Files from SQL Server Database using ASP.Net
This article is an extension of the same since was frequently asked on how to save file directly to database using the ASP.Net FileUpload Control
You can upload any files like images, Word document. Excel document, Portable Document Format (PDF), Text Files sand save them to Database
Database Design
Here I have created a Database called dbFiles and it has a table called tblFiles.
It has 4 Fields. The complete description is available in the Figure below


Table Structure

As you can see above for the id field I have set Identity Specification true, so that it automatically increments itself.
 
Field
Relevance
id
Identification Number
Name
File Name
Content Type
Content Type for the file
Data
File stored as Binary Data
 
Connection String
 
Below is the connection string to the database. You can modify it to suit yours
<connectionStrings>
<add name="conString" connectionString="Data Source=.\SQLEXPRESS;database=dbFiles; Integrated Security=true"/>
</connectionStrings >
 
To start with I have added a FileUpload control, a button and a Label to show messages
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="btnUpload" runat="server" Text="Upload"
OnClick="btnUpload_Click" />
<br />
<asp:Label ID="lblMessage" runat="server" Text=""
Font-Names = "Arial"></asp:Label>

And here is the snippet which is called on the Upload Button Click event
C#     
protected void btnUpload_Click(object sender, EventArgs e)
{
    // Read the file and convert it to Byte Array
    string filePath = FileUpload1.PostedFile.FileName;  
    string filename = Path.GetFileName(filePath);
    string ext = Path.GetExtension(filename);
    string contenttype = String.Empty;
 
    //Set the contenttype based on File Extension
    switch(ext)
    {
        case ".doc":
            contenttype = "application/vnd.ms-word";
            break;
        case ".docx":
            contenttype = "application/vnd.ms-word";
            break;
        case ".xls":
            contenttype = "application/vnd.ms-excel";
            break;
        case ".xlsx":
            contenttype = "application/vnd.ms-excel";
            break;
        case ".jpg":
            contenttype = "image/jpg";
            break;
        case ".png":
            contenttype = "image/png";
            break;
        case ".gif":
            contenttype = "image/gif";
            break;
        case ".pdf":
            contenttype = "application/pdf";
            break;
    }
    if (contenttype != String.Empty)
    {
 
        Stream fs = FileUpload1.PostedFile.InputStream;
        BinaryReader br = new BinaryReader(fs);
        Byte[] bytes = br.ReadBytes((Int32)fs.Length);
 
        //insert the file into database
        string strQuery = "insert into tblFiles(Name, ContentType, Data)" +
           " values (@Name, @ContentType, @Data)";
        SqlCommand cmd = new SqlCommand(strQuery);
        cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = filename;
        cmd.Parameters.Add("@ContentType", SqlDbType.VarChar).Value
          = contenttype;
        cmd.Parameters.Add("@Data", SqlDbType.Binary).Value = bytes;
        InsertUpdateData(cmd);
        lblMessage.ForeColor = System.Drawing.Color.Green;  
        lblMessage.Text = "File Uploaded Successfully";
    }
    else
    {
        lblMessage.ForeColor = System.Drawing.Color.Red;   
        lblMessage.Text = "File format not recognised." +
          " Upload Image/Word/PDF/Excel formats";
    }
}
 
 
VB.Net
  
Protected Sub btnUpload_Click(ByVal sender As Object, ByVal e As EventArgs)
  ' Read the file and convert it to Byte Array
  Dim filePath As String = FileUpload1.PostedFile.FileName
  Dim filename As String = Path.GetFileName(filePath)
  Dim ext As String = Path.GetExtension(filename)
  Dim contenttype As String = String.Empty
 
  'Set the contenttype based on File Extension
  Select Case ext
    Case ".doc"
      contenttype = "application/vnd.ms-word"
      Exit Select
    Case ".docx"
      contenttype = "application/vnd.ms-word"
      Exit Select
    Case ".xls"
      contenttype = "application/vnd.ms-excel"
      Exit Select
    Case ".xlsx"
      contenttype = "application/vnd.ms-excel"
      Exit Select
    Case ".jpg"
      contenttype = "image/jpg"
      Exit Select
    Case ".png"
      contenttype = "image/png"
      Exit Select
    Case ".gif"
      contenttype = "image/gif"
      Exit Select
    Case ".pdf"
      contenttype = "application/pdf"
      Exit Select
    End Select
    If contenttype <> String.Empty Then
      Dim fs As Stream = FileUpload1.PostedFile.InputStream
      Dim br As New BinaryReader(fs)
      Dim bytes As Byte() = br.ReadBytes(fs.Length)
 
      'insert the file into database
       Dim strQuery As String = "insert into tblFiles" _
       & "(Name, ContentType, Data)" _
       & " values (@Name, @ContentType, @Data)"
       Dim cmd As New SqlCommand(strQuery)
       cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = filename
       cmd.Parameters.Add("@ContentType", SqlDbType.VarChar).Value _
       = contenttype
       cmd.Parameters.Add("@Data", SqlDbType.Binary).Value = bytes
       InsertUpdateData(cmd)
       lblMessage.ForeColor = System.Drawing.Color.Green
       lblMessage.Text = "File Uploaded Successfully"
     Else
       lblMessage.ForeColor = System.Drawing.Color.Red
       lblMessage.Text = "File format not recognised." _
       & " Upload Image/Word/PDF/Excel formats"
     End If
  End Sub
 
The above code simply reads the uploaded File as Stream and then converts the Stream to Byte array using Binary Reader and then the finally the byte arrays is saved to the database InsertUpdateData method executes the query to save the data in database
The InsertUpdateData function is given below
    
C#
private Boolean InsertUpdateData(SqlCommand cmd)
{
    String strConnString = System.Configuration.ConfigurationManager
    .ConnectionStrings["conString"].ConnectionString;
    SqlConnection con = new SqlConnection(strConnString);
    cmd.CommandType = CommandType.Text;
    cmd.Connection = con;
    try
    {
        con.Open();
        cmd.ExecuteNonQuery();
        return true;
    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
        return false;
    }
    finally
    {
        con.Close();
        con.Dispose();
    }
}
 
VB.Net
 
Public Function InsertUpdateData(ByVal cmd As SqlCommand) As Boolean
    Dim strConnString As String = System.Configuration.
    ConfigurationManager.ConnectionStrings("conString").ConnectionString
    Dim con As New SqlConnection(strConnString)
    cmd.CommandType = CommandType.Text
    cmd.Connection = con
    Try
      con.Open()
      cmd.ExecuteNonQuery()
      Return True
    Catch ex As Exception
      Response.Write(ex.Message)
      Return False
    Finally
      con.Close()
      con.Dispose()
    End Try
End Function
 
This completes the article. You can download the source code in VB.Net and C# from the link below.

Automated Email Notifications using SQL Server Job Schedular

Most of the times there are requirements when we need to send automatic notification emails to all or specific email address in the database based on some condition.
In such scenario we can take help from SQL Server using its following two properties.
1.     SQL Server Emailing
2.     SQL Server Scheduling
For example send birthday wishes to all customers whose birthday matches the current day.
Hence I decided I’ll explain the same here.
For this tutorial I have created a database Customers with a table called CustomerDetails with the following fields
1. ID
2. Name
3. BirthDate
4. Email
The sample data is shown in the figure below

Customers details table

In order to send emails using SQL Server you can refer my article Send SMTP Email using SQL Server
In this tutorial I am using the same stored procedure to send emails.
I have written the SQL script shown below. The SQL script loops through the CustomerDetails table and matches all records birth day and birth month with the current day and month. If the two matches then it sends an email to the particular customer to its email address stored in the table.
           
DECLARE
@out_desc VARCHAR(1000),
@out_mesg VARCHAR(10)
DECLARE @name VARCHAR(20),
@birthdate datetime,
@email NVARCHAR(50)
DECLARE @body NVARCHAR(1000)
DECLARE C1 CURSOR READ_ONLY
FOR
SELECT [name], [birthdate], [email]
FROM Customers
OPEN C1
FETCH NEXT FROM C1 INTO
@name, @birthdate, @email
WHILE @@FETCH_STATUS = 0
BEGIN
      IF DATEPART(DAY,@birthdate) = DATEPART(DAY,GETDATE())
      AND DATEPART(MONTH,@birthdate) = DATEPART(MONTH,GETDATE())
      BEGIN
            SET @body = '<b>Happy Birthday ' + @name +
            '</b><br />Many happy returns of the day'
            + '<br /><br />Customer Relationship Department'
            EXEC sp_send_mail
            sender@abc.com',
            'xxxxxxx',
            @email,
            'Birthday Wishes',
            @body,
            'htmlbody',
            @output_mesg = @out_mesg output,
            @output_desc = @out_desc output
            PRINT @out_mesg
            PRINT @out_desc
      END
      FETCH NEXT FROM C1 INTO
      @name, @birthdate, @email
END
CLOSE C1
DEALLOCATE C1
Now to make the above script automatically run daily we will need to schedule it to run daily using the SQL Server Job Scheduler.
Below I’ll explain how to schedule the script to run daily using Job Scheduler
  
Step 1
In the SQL Server Enterprise Manager expand the Management Tab and select SQL Server Agent Node.
Refer figure below.


Management Tab

Step 2
On the Right Panel Select Job, Right Click it and select New Job from context menu to open New Job Window.
Refer figure below.


Create a New Job

Step 3
In the New Job Window, in General Tab enter the following details
1.     Name - Name of the Job
2.     Description – Description of the Job (Optional)
3.     Enabled – Determines whether job is enabled or disabled
Refer figure below


New Job - General Tab

Step 4
In the New Job Window, in Steps Tab click New Step to open a New Step Window
In the New Step Window enter the following details
1.     Step Name - Name of the Step
2.     Type  – Select Transact SQL Script
3.     Database – Select the database on which you want to run the script.
4.     Command – Paste the SQL Script which you wish the Job Scheduler to run.
Refer figure below


New Job - Steps Tab

Step 5
In the New Job Window, in Schedules Tab click New Schedule to open a New Schedule Window
In the New Schedule Window enter the following details
1.     Name - Name of the Step
2.     Enabled – Determines whether Schedule is enabled or disabled
3.     Schedule Type – Select Recurring schedule type since we need to run it daily
Refer figure below


New Job - Schedule Tab - New Schedule

Step 6
Next click on Change button in the Schedule Window to set the schedule
In the Edit Schedule Window enter the following details
1.     Occurs – Daily since we need to run it daily
2.     Daily Frequency – Since we need to run once a day, select the time you wish to run
3.     Start date – Select date from when you want the schedule to run.
Refer figure below


New Job - Schedule Tab - Edit Recurring Schedule

Step 7
That’s it and your job is created. You will see a new entry in the SQL Server agent -----> Jobs
To start the job right click the job and in the context menu click Start Job
Refer figure below


Start Scheduled Job

This completes the tutorial for creating scheduled job in SQL Server. Below is the Birthday email that will be received by the customer
Refer figure below


Received Birthday Email Notification