views:

158

answers:

6

How to store the file which is uploaded by the user to the database ? I want to store the file in the database how can we do that ? In the back-end I am using sql with c#.net application.

A: 

One solution that will keep your db size down is to store the location of the file on the server. IE a file path.

However you will have to make a manager if you ever want to move files about.

Kieran
A: 

You can use a blob field type. When you read the file in from a StreamReader convert it to a byte array and then insert that into the blob field.

The reverse procedure when you want to read it, get the blob as a byte array, read it into a streamreader and write that to the response buffer.

Michael Shimmins
+3  A: 

Assuming SQL 2005 or later, I would use a VarBinary(MAX) field. Pass the uploaded file as a byte[] to the insert statement. According to Microsoft, since SQL 2005, storing large chunks of data (files and images) in the DB no longer decreases performance to a great extent.

eg:

public void SaveFileToDB(string description, byte[] file)
{
    using (SqlConnection con = new SqlConnection(conStr)
    {
        con.Open();
        using (SqlCommand cmd = con.CreateCommand())
        {
            cmd.Parameters.Add("@Description", SqlDbType.VarChar, description);
            cmd.Parameters.Add("@File", SqlDbType.VarBinary, file);
            cmd.CommandText = "UploadedFileUpdate";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.ExecuteNonQuery();
        }
    }
}

If you have SQL 2008, see Ron Klein's suggestion.

Robert Wagner
I still wouldnt recommend it unless 1) you have a fairly small number of files and a small file size or 2) you have the infrastructure to support the scaling of the solution. I have worked in two shops where my first job was to figure out how they could move **massive** DBs that had grown out of control because of the practice of storing files in the db, especially when those files where highly redundant (as determined by MD5 checksums)
GrayWizardx
@GrayWizardx agreed, but I am assuming that Harikrishna has already decided to store in the DB. There are some situations (like shared hosting) where you cannot write to the file system.
Robert Wagner
@Robert Wagner, good point. I always seem to forget about hosted stuff. A bad habit on my part, and a good reminder. Thanks.
GrayWizardx
@GrayWizardx: up to about 1 MB in size, storing the file in the DB is preferably to storing it in the filesystem. Also, putting the VARBINARY(MAX) columns into a separate table, possibly even separate filegroup, can help keep things in check.
marc_s
I guess Roberts solution is the one suitable for this scenario@Marc good point
Aneef
@Marc_s I am not sure how you come to that analysis, I would think it was highly dependent on its usage, frequency of access, etc. One scenario for instance is having the file available for multiple points of access (think field offices), replication lag alone would make disk based solutions worth considering (not necessarily implementing), also my point was more about scaling of the solution and what happens when it gets big. I guess I have spent too much time on really big implementations and not more practical/realistic ones. :)
GrayWizardx
@GrayWizardx: I didn't - Microsoft Research did - see "To Blob or Not To Blob": http://research.microsoft.com/apps/pubs/default.aspx?id=64525
marc_s
@marc_s, Thanks for the link, will check it out.
GrayWizardx
A: 

Upload/Import Download/Export a File to/from Oracle DB

Although it's implemented for an Oracle database I think you can get the idea reading the post.

Leniel Macaferi
+2  A: 

MS SQL Server 2008 (and above, I guess) offers FileStream data type. Just Google for it (or Bing it, whatever :-)), I think you'll find what you need.

Ron Klein
+2  A: 

This solution works for SQL SERVER 2005/2008.

You have to create table with VARBINARY(MAX) as one of the columns. In my case I've created Table Raporty with column RaportPlik being VARBINARY(MAX) column.

Below there are couple of support functions you can modify for your needs:

    public static void databaseFilePut(string varFilePath) {
        byte[] file;
        using (var stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read)) {
            using (var reader = new BinaryReader(stream)) {
                file = reader.ReadBytes((int) stream.Length);

            }

        }
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlWrite = new SqlCommand("INSERT INTO Raporty (RaportPlik) Values(@File)", varConnection)) {
            sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file;
            sqlWrite.ExecuteNonQuery();
        }
    }
    public static void databaseFileRead(string varID, string varPathToNewLocation) {
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) {
            sqlQuery.Parameters.AddWithValue("@varID", varID);
            using (var sqlQueryResult = sqlQuery.ExecuteReader())
                if (sqlQueryResult != null) {
                    sqlQueryResult.Read();
                    var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))];
                    sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length);
                    using (var fs = new FileStream(varPathToNewLocation, FileMode.Create, FileAccess.Write)) fs.Write(blob, 0, blob.Length);
                }
        }
    }
    public static MemoryStream databaseFileRead(string varID) {
        MemoryStream memoryStream = new MemoryStream();
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) {
            sqlQuery.Parameters.AddWithValue("@varID", varID);
            using (var sqlQueryResult = sqlQuery.ExecuteReader())
                if (sqlQueryResult != null) {
                    sqlQueryResult.Read();
                    var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))];
                    sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length);
                    //using (var fs = new MemoryStream(memoryStream, FileMode.Create, FileAccess.Write)) {
                    memoryStream.Write(blob, 0, blob.Length);
                    //}
                }
        }
        return memoryStream;
    }

First method is to put file into database from drive, second method is to get file and save it on drive, and 3rd method is to get file from database and put it as MemoryStream so you can some other stuff with it then just writing it to drive.

This 4th method is to put MemoryStream into database:

public static int databaseFilePut(MemoryStream fileToPut) {
        int varID = 0;
        byte[] file = fileToPut.ToArray();
        const string preparedCommand = @"
                    INSERT INTO [dbo].[Raporty]
                               ([RaportPlik])
                         VALUES
                               (@File)
                        SELECT [RaportID] FROM [dbo].[Raporty]
            WHERE [RaportID] = SCOPE_IDENTITY()
                    ";
        using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) {
            sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file;

            using (var sqlWriteQuery = sqlWrite.ExecuteReader())
                while (sqlWriteQuery != null && sqlWriteQuery.Read()) {
                    varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0;
                }
        }
        return varID;
    }
MadBoy