The sample web site has three main files: default.aspx, cache.aspx,
and uploadblob.aspx. Download, compile and run the web site. Make sure to
create the SQL table and stored procedures using the Upload.sql file.
Put a break point at the top of the Page_Load method of the
uploadblob.aspx.cs file. This is the area of code this article focuses on.
The first time you load the file, nothing will appear except a link to the upload
page on the default.aspx. As you upload images, this page will show a
GridView listing those images.
Click on the Upload File link, and you will go to the upload page. The
uploadblob.aspx file is short with nothing specific to this solution:
<form id="form1" runat="server" >
<div>
Large File to Upload<br />
<asp:FileUpload ID="FileUpload1" runat="server" /></div>
<asp:Button ID="Button1" runat="server" Text="Upload" />
</form>
Upload the ascent.jpg file from the /images directory.
Your breakpoint should now be active in Visual Studio at the top of the
Page_Load method of uploadblob.aspx.cs.
The if statement is there so that a previously uploaded file
can be modified/overwritten with a new file. This is part of the caching article code.
In this first iteration of the code, the if statement doesn't
apply so the else statement is hit.
The code grabs the file as a Stream object, along with the file name
and the content or mime type. The mime type is important for sending
the file back to the browser so that the appropriate plug-in or
application can render the file.
// DFB: Upload goes into stream
Stream myStream = FileUpload1.PostedFile.InputStream;
_name = FileUpload1.FileName;
_contentType = FileUpload1.PostedFile.ContentType;
Next a Byte array is created of 1024 bytes. The size of 1024 can be
considered artibrary in this example. You will want to determine the
best size for your chunks given your memory on the web server and
the sql server as well as general size of files uploaded and the
frequency with which they are uploaded.
// DFB: Create buffer for stream
Byte[] myBuffer;
myBuffer = new byte[1024];
The code then checks the state for the FileGuid value. If the value is not found,
a new guid is created and a row is inserted into the SQL Table:
// DFB: If new blob, create guid and row
if (ViewState["FileGuid"] == null)
{
// DFB: Create new guid/file
_guid = System.Guid.NewGuid();
// DFB: Create new row for this data
CreateRow();
}
else
{
// DFB: This is the postback of an update (not a new file)
_guid = new Guid(ViewState["FileGuid"].ToString());
}
The SQL for the CreateRow function is:
INSERT INTO UploadBytesOfBlob (FileGuid, Name, ContentType, LastModifiedDate, FirstModifiedDate)
VALUES (@FileGuid, @Name, @ContentType, GetDate(), GetDate())
Next, the row needs to be cleared. You must clear because you can not append
to a null column. The clear is accomplished by adding zero data.
// DFB: Can't append to null column so use clear first
Clear();
The cooresponding SQL for the clear funtion is
--DFB nulls the column
UPDATE UploadBytesOfBlob
SET Content = CONVERT(varbinary(max),0)
WHERE FileGuid = @FileGuid
--DFB writes
UPDATE UploadBytesOfBlob
SET LastModifiedDate = GetDate(),
Content.WRITE(NULL,0,0),
Size = 0,
NumberOfChunks=1
WHERE FileGuid = @FileGuid
The Content.Write(Null,0,0) clause uses the .Write function that
is only available to varchar(max), nvarchar(max), or varbinary(max) column types.
The .Write function specifies what part of the column data to modify.
The three parameters for the .Write function are the content of the
column, the offset into the column, and the length of the existing content to
replace. By using the above parameter values of (Null,0,0), the column content
is truncated to the beginning of the column.
Now the Stream of the Upload control is fed right into the database one chunk at a time.
// DFB: Read upload and stream into database in chunks
while(myStream.Read(myBuffer, 0, myBuffer.Length)>0)
{
//DFB: Append stream chunk to end of database row/column
AppendChunk(myBuffer);
}
The associated AppendChunk sql stored procedure is
UPDATE UploadBytesOfBlob
SET Content.WRITE (@Data, NULL, NULL)
WHERE FileGuid = @FileGuid
UPDATE UploadBytesOfBlob
SET Size = LEN(Content),
LastModifiedDate = GetDate(),
NumberOfChunks = NumberOfChunks + 1
WHERE FileGuid = @FileGuid
The new parameters for the .Write function indicate that the data should be
appended to the current column's content. The second update statement modifies the
Size, LastModifiedDate, and the NumberOfChunks columns to reflect the updated Content value.
The stream is closed and the page redirects to the default.aspx page.
myStream.Close();
Response.Redirect("~/default.aspx");
The default.aspx page now shows the ascent.jpg information in the GridView.
You can click on the FileGuid link to see the content loaded from the database
via the Cache.aspx file. The file is streamed down from the database
using the same chunk method to read the content and write to a file. The web
server then returns the file to the browser. The Upload link on the row allows
you to change the content of the row. The content is completely cleared every
time the file is uploaded via this chunking method.