Wednesday, April 14, 2010

file upload in chunks using silverlight and webservice

How Do I?

File upload in chunks throught Silverlight and webservice


This is a very basic file upload control that can upload file in chunks using a webservice. In this article I will explain you how to upload file in chunks and with this article I have uploaded the whole project. you can use it to extend or use it as it is.
This control is in three parts…

1- Silverlight
2- WebService
3- Website

The only difficult part is the Silverlight one. It’s not very difficult but it requires understanding the basics of how to convert the file in chunks so data can be uploaded in server in small chunks. This will be very useful in many scenarios e.g. large file upload.

Let’s start with Silverlight

SilverLight

We need a Silverlight control that can upload file in chunks. Along with the chunks we need a way to show the progress of uploaded file. GUI is simple, there is one browse button that will open the OpenFileDialog and will help user to pick a file. When user will select the file, the file name will be shown in a label and uploading will begin. A progress bar will be displayed to show that file is uploading in the server. After the whole file will upload, the success message will be display. I end up making the following simple GUI





What happen behind is also very simple…
Let’s dig the Browse button click event. When user will click the browse button, openfiledialog will be displayed. User will select a file and event will check if user has selected a file and start to read the file by using a file stream. Then this stream will get converted into bytes. These bytes will get converted into chunks and this control will start sending chunks and after every successful chunk, this control will send the next chunk of file. Chunk size is fixed in this program to 15kB. Here is the code of browse button event




Next thing is how convert to chunk function is working.It is really simple; first it will count the total chunks by dividing the number of bytes with the upload chunk size then with will start to add this chunk in a list of chunks. I am preparing this list of chunks as a global variable so I can send one chunk, maintain its index and when I will receive the success of uploaded chunk, I will send the next file chunk.
Here is the code of file convert to chunks function




Next step is to start uploading chunk. This control uses the webservice to upload the file and upload function will simple send a chunk of bytes to webservice along with the file name. I am using the file real name which user will select but this is not practical so to use this control you should come up with a unique file name to avoid conflicting file name uploading by different users also different file name is necessary for this control to work appropriately.
Here is the code of upload file function



This function is called async and when this function will complete we will get an event and in this event we will make sure that last chunk is uploaded and then we will send the next chunk. Here is the code



That’s the end of Silverlight control and most of the logic. There are just two tiny function remains. One is in the webservice and second one in the business layer or in a class that stores in you app_code folder.

WebService

Webservice has only one function and this function receives the uploaded bytes and sends it to the uploading class in business layer. Here is the code



Class logic inside your app_code/business layer

Logic of saving chunks is as follows,
Function will check if it is a new file by checking if file does not exist in the pre defined directory. If it is a new file, it will create the file using file stream and will write the bytes to this file and close the stream. Next time when it will receive the next chunk, it will see if this file exists in the directory and as this file already exist, it will open the file in a stream and write the bytes to this stream and close the stream. This way chunks will be written in file until it will successfully complete.
Here is the code


you can download the complete solution from this link click here
 http://rapidshare.com/files/375917799/Silverlight_file_upload_chunks_webservice.zip
And that is it, I hope this effort will help and if anybody needs more help, I will be happy to help him.

15 comments:

  1. Hi,
    Article is very nice. But when I tried uploading a 2.22 GB file it failed in following line.
    byte[] file=new byte[fs.length];
    Arithmetic overflow exception.
    I think we really need to further analyze the procedure.

    Thanks,
    Thani

    ReplyDelete
  2. Thani,
    I think this exception is occurring due to the length is increasing the size of maximum byte allocations. This is a very basic chunk upload control. Alot of things could be done here but due to lack of time, i am unable to do these things.

    ReplyDelete
  3. thank you so much for sharing your code. I've been struggling with mine. Same idea uploading chunks of bytes; however, i used an array to store those chunks and while uploading it skips some bytes (some elements in the array don't hold the entire chunk!) I assume the size of each element is not that big enough to hold the whole byte's size!
    Anyway, using a List totally helped. so thank you again

    ReplyDelete
  4. i dont think using array has any problem even though i did not tried it yet. Maybe when u converting it in chunks, it skipped some bytes due to wrong conditions or somethings because at the end list or array, they will both convert to a series of bytes and passed to web service.

    Glad to help

    ReplyDelete
  5. Great solution. Thank you.. What about saving file in chunks in database, not in file. Do you have any ideas?

    ReplyDelete
  6. you could save the file in database when file is completely uploaded in server. If you will try to save each chunk and append next in file it will affect your database performance.
    You need custom implementation of SaveFile method for this purpose, other detail will remain the same.
    if you need more help about code, let me know.

    ReplyDelete
  7. what about BLOB? if i need to upload, maybe 10 mb file in database... its big insert in database if i put it in once... i think in that case it will affect more database and application performance..

    Here is good example about inserting data in chunks in sql...

    http://msdn.microsoft.com/en-us/library/3517w44b.aspx

    But I still can connect control with this proposed solution...

    ReplyDelete
  8. i read the above indicated article and its clear to me that it is a good idea and possible.
    Your question about how to connect it with my solution would require a change in silverligh,webservice and re written of savefilechunk function.

    in silverligh update the uploadchunks function and add a new parameter of current index. you can calculate this by index*chunksize

    in webservice add a new parameter current index and pass the calculated index to web service.

    webservice will pass this index to business layer save file chunks functions.

    Now you have to connect this to save data in database.

    you have
    1- buffer chunk data
    2- pointer(index)
    3- file name

    you can update the database with the following query

    int bufferLen = chunk.length;

    SqlCommand appendToPhoto = new SqlCommand(
    "UPDATETEXT files @Pointer @Offset 0 @Bytes",
    connection);

    SqlParameter ptrParm = appendToPhoto.Parameters.Add(
    "@Pointer", SqlDbType.Binary, 16);
    ptrParm.Value = pointer;
    SqlParameter photoParm = appendToPhoto.Parameters.Add(
    "@Bytes", SqlDbType.Image, chunk);
    SqlParameter offsetParm = appendToPhoto.Parameters.Add(
    "@Offset", SqlDbType.Int,index);



    photoParm.Value = buffer;
    appendToPhoto.ExecuteNonQuery();




    i think this will solve your problem. I did not tested it but i hope this will work

    ReplyDelete
  9. great sample,
    but how can I accelerate the upload process. because 10mb data is uploaded about 1 minutes.

    ReplyDelete
  10. you can use a bigger chunk, that would make it faster. Try to optimize chunk size according to yoru need.

    ReplyDelete
  11. Can't download the source code file, it is missing. Is there a way to get it? Thanks in advance.

    ReplyDelete
  12. Me too. Cant download

    ReplyDelete
  13. yeah source would be helpful

    ReplyDelete
  14. Can't download the code please provide right share link to download sample code

    ReplyDelete