Introduction
This my first article/tip here. I want to post a little guide to develop a simple "async file uploader class" for Silverlight 3. I will post the client-side code and the server-side code.
I'm really sorry about my English.
Using the Code
File upload with Silverlight can be performed in many ways, but this is the one I prefer.
Step 1 (Silverlight Application): Create the class with all the sub, function, event and....
Imports System.ComponentModel
Imports System.IO
Public Class cFileUploader
Public Event UploadStarted(ByVal sender As cFileUploader)
Public Event UploadCompleted(ByVal sender As cFileUploader)
Public Event UploadProgressChanged(ByVal sender As cFileUploader, _
ByVal currentbytes As Integer, ByVal totalbytes As Integer, _
ByVal percentual As Integer)
Public Event UploadFailed(ByVal sender As cFileUploader, ByVal ex As Exception)
Dim WithEvents bgw As BackgroundWorker
Dim WithEvents wc As WebClient
Dim input As Stream
Dim output As Stream
Dim byteread As Integer = -1
Dim bytereadcount As Integer = 0
Public BufferLenght As Integer = 8138
Public FileReceiverUrl As String = "http://localhost:50245/filereceiver.ashx"
Public File As FileInfo
Sub New(ByVal file As FileInfo)
Me.File = file
End Sub
Sub New()
End Sub
Public Sub UploadFileAsync()
Me.UploadFileAsync(Me.File.Name, Me.File.OpenRead)
End Sub
Public Sub UploadFileAsync(ByVal filename As String)
Me.UploadFileAsync(filename.Trim, Me.File.OpenRead)
End Sub
Public Sub UploadFileAsync(ByVal file As FileInfo)
Me.File = file
Me.UploadFileAsync(Me.File.Name, Me.File.OpenRead)
End Sub
Public Sub UploadFileAsync(ByVal filename As String, ByVal file As FileInfo)
Me.File = file
Me.UploadFileAsync(filename, Me.File.OpenRead)
End Sub
Private Sub UploadFileAsync(ByVal filename As String, ByVal data As Stream)
Try
RaiseEvent UploadStarted(Me)
Me.bgw = New BackgroundWorker
Me.bgw.WorkerReportsProgress = True
Me.wc = New WebClient
Me.input = data
Me.byteread = -1
Me.bytereadcount = 0
Dim ub As UriBuilder = New UriBuilder(Me.FileReceiverUrl)
ub.Query = String.Format("filename={0}", filename)
Me.wc.OpenWriteAsync(ub.Uri)
Catch ex As Exception
RaiseEvent UploadFailed(Me, ex)
End Try
End Sub
Private Sub wc_OpenWriteCompleted(ByVal sender As Object, _
ByVal e As System.Net.OpenWriteCompletedEventArgs) _
Handles wc.OpenWriteCompleted
Try
Me.output = e.Result
Me.bgw.RunWorkerAsync()
Catch ex As Exception
RaiseEvent UploadFailed(Me, ex)
End Try
End Sub
Private Sub bgw_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
Try
Me.bgw.ReportProgress(0)
Dim buffer(Me.BufferLenght) As Byte
If byteread <> 0 Then
bytereadcount = bytereadcount + byteread
byteread = Me.input.Read(buffer, 0, buffer.Length)
Me.output.Write(buffer, 0, byteread)
End If
Catch ex As Exception
Me.byteread = 0
RaiseEvent UploadFailed(Me, ex)
End Try
End Sub
Private Sub bgw_ProgressChanged(ByVal sender As Object, _
ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
Handles bgw.ProgressChanged
Try
Dim tot As Integer = Me.File.OpenRead.Length
Dim cur As Integer = Math.Max(bytereadcount, 0)
Dim prc As Integer = CInt(100 * (cur / tot))
RaiseEvent UploadProgressChanged(Me, cur, tot, prc)
Catch ex As Exception
End Try
End Sub
Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles bgw.RunWorkerCompleted
Try
If byteread <> 0 Then
Me.bgw.RunWorkerAsync()
Else
Me.output.Close()
Me.input.Close()
RaiseEvent UploadCompleted(Me)
End If
Catch ex As Exception
RaiseEvent UploadFailed(Me, ex)
End Try
End Sub
End Class
Here the only thing to change is the URL of the "filereceiver.ashx" explained in STEP 2.
Step 2 (Hosting Web Site): Add to the project (the web/server side that publics the Silverlight app) a "Generic Handler" (ASHX file).
I inserted the "filereceiver.ashx" file with the following code:
Imports System.Web
Imports System.Web.Services
Imports System.IO
Public Class FileReceiver
Implements System.Web.IHttpHandler
Sub ProcessRequest(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest
Dim filename As String = context.Request.QueryString("filename").ToString
Dim destFolder As String
destFolder = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory)
destFolder = context.Server.MapPath("~/App_Data/FilesArchive/")
destFolder = Path.GetFullPath("c:\temp\")
Using inputStream As Stream = context.Request.InputStream
Using fs As FileStream = New FileStream_
(destFolder + filename, FileMode.Create, FileAccess.Write, FileShare.Read)
Dim buffer(inputStream.Length) As Byte
inputStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, buffer.Length)
fs.Flush()
End Using
End Using
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
The code is quite simple. The only thing to change is the destination folder "destFolder" and apply the correct permissions of the web server application folders.
I hope you enjoy this.
Bye bye !!!