Click here to Skip to main content
15,896,464 members
Articles / Programming Languages / C#

Amazon S3 Sync

Rate me:
Please Sign up or sign in to vote.
4.92/5 (6 votes)
1 Dec 2010Apache5 min read 48K   1.6K   23  
Synchronize files from your computer to Amazon S3.
Imports System.Windows.Forms

Public Class FormUpload

    Dim WithEvents MyCalculateHash As SprightlySoftAWS.S3.CalculateHash
    Dim WithEvents MyUpload As SprightlySoftAWS.S3.Upload
    Dim WithEvents UploadBackgroundWorker As System.ComponentModel.BackgroundWorker
    Dim WithEvents CalculateHashBackgroundWorker As System.ComponentModel.BackgroundWorker

    Private Sub FormUpload_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        MyCalculateHash = New SprightlySoftAWS.S3.CalculateHash
        MyUpload = New SprightlySoftAWS.S3.Upload

        CalculateHashBackgroundWorker = New System.ComponentModel.BackgroundWorker
        UploadBackgroundWorker = New System.ComponentModel.BackgroundWorker

        LabelAction.Text = "Waiting"
        ProgressBarTransfered.Value = 0
        LabelBytesTransfered.Text = "0 bytes / 0 bytes"

    End Sub

    Private Sub EnableDisableStart()
        TextBoxUploadFileName.Enabled = False
        TextBoxUploadBucketName.Enabled = False
        TextBoxUploadKeyName.Enabled = False
        TextBoxUploadContentType.Enabled = False
        CheckBoxUploadMakePublic.Enabled = False
        ButtonUploadBrowse.Enabled = False
        ButtonUploadFile.Enabled = False

        ButtonAbort.Enabled = True
        LabelAction.Enabled = True
        ProgressBarTransfered.Enabled = True
        LabelBytesTransfered.Enabled = True

        LabelAction.Text = "Waiting"
        ProgressBarTransfered.Value = 0
        LabelBytesTransfered.Text = "0 bytes / 0 bytes"
    End Sub

    Private Sub EnableDisableEnd()
        TextBoxUploadFileName.Enabled = True
        TextBoxUploadBucketName.Enabled = True
        TextBoxUploadKeyName.Enabled = True
        TextBoxUploadContentType.Enabled = True
        CheckBoxUploadMakePublic.Enabled = True
        ButtonUploadBrowse.Enabled = True
        ButtonUploadFile.Enabled = True

        ButtonAbort.Enabled = False
        LabelAction.Enabled = False
        ProgressBarTransfered.Enabled = False
        LabelBytesTransfered.Enabled = False

        LabelAction.Text = "Waiting"
        ProgressBarTransfered.Value = 0
        LabelBytesTransfered.Text = "0 bytes / 0 bytes"
    End Sub


    Private Sub ButtonUploadBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonUploadBrowse.Click
        Dim OpenFileDialog As New System.Windows.Forms.OpenFileDialog
        OpenFileDialog.Multiselect = False
        OpenFileDialog.FileName = ""
        OpenFileDialog.ShowDialog()

        If OpenFileDialog.FileName <> "" AndAlso System.IO.File.Exists(OpenFileDialog.FileName) = True Then

            TextBoxUploadFileName.Text = OpenFileDialog.FileName
            TextBoxUploadKeyName.Text = System.IO.Path.GetFileName(OpenFileDialog.FileName)

            'set the content type from the file's extension
            'the S3 Helper class contains a function that returns a dictionary of extensions and associated content types
            Dim MyHelper As New SprightlySoftAWS.S3.Helper
            Dim ContentTypesDictionary As Dictionary(Of String, String)
            ContentTypesDictionary = MyHelper.GetContentTypesDictionary

            Dim MyExtension As String
            MyExtension = LCase(System.IO.Path.GetExtension(OpenFileDialog.FileName))

            If ContentTypesDictionary.ContainsKey(MyExtension) = True Then
                TextBoxUploadContentType.Text = ContentTypesDictionary(MyExtension)
            Else
                TextBoxUploadContentType.Text = ""
            End If

        End If
    End Sub

    Private Sub ButtonUploadFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonUploadFile.Click
        EnableDisableStart()

        If System.IO.File.Exists(TextBoxUploadFileName.Text) = True Then

            'Start by calculating the MD5 hash of the file.  This will be sent to Amazon in the 
            'upload to make sure it arrives correctly.
            LabelAction.Text = "Calculating MD5 hash"
            Application.DoEvents()

            'Run the hash calculation in a BackgroundWorker process.  Calculating the hash of a
            'large file will take a while.  Running the process in a BackgroundWorker will prevent
            'the form from locking up.

            'Use a hash table to pass parameters to the function in the BackgroundWorker.
            Dim CalculateHashHashTable As New Hashtable
            CalculateHashHashTable.Add("LocalFileName", TextBoxUploadFileName.Text)

            CalculateHashBackgroundWorker.RunWorkerAsync(CalculateHashHashTable)

        Else
            EnableDisableEnd()
            MessageBox.Show("The local file does not exist.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If

    End Sub

    Private Sub CalculateHashBackgroundWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles CalculateHashBackgroundWorker.DoWork
        'Call the CalculateMD5FromFile function and set the result.  When the function is complete
        'the RunWorkerCompleted event will fire.  Use the LocalFileName value from the passed hash table.
        e.Result = MyCalculateHash.CalculateMD5FromFile(e.Argument("LocalFileName"))
    End Sub

    Private Sub CalculateHashBackgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles CalculateHashBackgroundWorker.RunWorkerCompleted

        'If the CalculateMD5FromFile function was successful upload the file.
        If MyCalculateHash.ErrorNumber = 0 Then

            LabelAction.Text = "Uploading file"
            Application.DoEvents()

            'Set the extra request headers to send with the upload
            Dim ExtraRequestHeaders As New Dictionary(Of String, String)

            If TextBoxUploadContentType.Text <> "" Then
                ExtraRequestHeaders.Add("Content-Type", TextBoxUploadContentType.Text)
            End If

            If CheckBoxUploadMakePublic.Checked = True Then
                ExtraRequestHeaders.Add("x-amz-acl", "public-read")
            End If

            'Use the MD5 hash that was calculated previously.
            ExtraRequestHeaders.Add("Content-MD5", e.Result)

            Dim RequestURL As String
            RequestURL = MyUpload.BuildS3RequestURL(True, "s3.amazonaws.com", TextBoxUploadBucketName.Text, TextBoxUploadKeyName.Text, "")

            Dim RequestMethod As String = "PUT"

            ExtraRequestHeaders.Add("x-amz-date", DateTime.UtcNow.ToString("r"))

            Dim AuthorizationValue As String
            AuthorizationValue = MyUpload.GetS3AuthorizationValue(RequestURL, RequestMethod, ExtraRequestHeaders, FormMain.TextBoxAWSAccessKeyId.Text, FormMain.TextBoxAWSSecretAccessKey.Text)
            ExtraRequestHeaders.Add("Authorization", AuthorizationValue)

            'Create a hash table of of parameters to sent to the upload function.
            Dim UploadHashTable As New Hashtable
            UploadHashTable.Add("RequestURL", RequestURL)
            UploadHashTable.Add("RequestMethod", RequestMethod)
            UploadHashTable.Add("ExtraRequestHeaders", ExtraRequestHeaders)
            UploadHashTable.Add("LocalFileName", TextBoxUploadFileName.Text)

            'Run the UploadFile call in a BackgroundWorker to prevent the Window from freezing.
            UploadBackgroundWorker.RunWorkerAsync(UploadHashTable)

        Else
            EnableDisableEnd()
            MessageBox.Show(MyCalculateHash.ErrorDescription, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If

    End Sub

    Private Sub UploadBackgroundWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles UploadBackgroundWorker.DoWork
        'Run the UploadFile call.
        e.Result = MyUpload.UploadFile(e.Argument("RequestURL"), e.Argument("RequestMethod"), e.Argument("ExtraRequestHeaders"), e.Argument("LocalFileName"))
    End Sub

    Private Sub UploadBackgroundWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles UploadBackgroundWorker.RunWorkerCompleted

        Debug.Print("")
        Debug.Print(MyUpload.LogData)
        Debug.Print("")

        EnableDisableEnd()

        If e.Result = True Then
            MessageBox.Show("Upload complete.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else

            'Show the error message.
            Dim ResponseMessage As String

            If MyUpload.ResponseString = "" Then
                ResponseMessage = MyUpload.ErrorDescription
            Else
                Dim XmlDoc As New System.Xml.XmlDocument
                XmlDoc.LoadXml(MyUpload.ResponseString)

                Dim XmlNode As System.Xml.XmlNode
                XmlNode = XmlDoc.SelectSingleNode("/Error/Message")

                ResponseMessage = XmlNode.InnerText
            End If

            MessageBox.Show(ResponseMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)

        End If

    End Sub

    Private Sub ButtonAbort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAbort.Click
        'Abort the CalculateHash call or Upload call depending on what is taking place.
        If MyCalculateHash.State = 1 Then
            MyCalculateHash.Abort()
        ElseIf MyUpload.State = 1 Then
            MyUpload.Abort()
        End If
    End Sub

    Private Sub MyCalculateHash_ProgressChangedEvent() Handles MyCalculateHash.ProgressChangedEvent
        If Me.InvokeRequired = True Then
            Me.Invoke(New MethodInvoker(AddressOf MyCalculateHash_ProgressChangedEvent))
        Else
            'Update the progress bar when the ProgressChangedEvent is fired.
            If MyCalculateHash.BytesTotal > 0 Then
                ProgressBarTransfered.Value = (MyCalculateHash.BytesProcessed / MyCalculateHash.BytesTotal) * 100

                Dim MyHelper As New SprightlySoftAWS.S3.Helper
                LabelBytesTransfered.Text = MyHelper.FormatByteSize(MyCalculateHash.BytesProcessed) & " / " & MyHelper.FormatByteSize(MyCalculateHash.BytesTotal)
            End If
        End If
    End Sub

    Private Sub MyUpload_ProgressChangedEvent() Handles MyUpload.ProgressChangedEvent
        If Me.InvokeRequired = True Then
            Me.Invoke(New MethodInvoker(AddressOf MyUpload_ProgressChangedEvent))
        Else
            'Update the progress bar when the ProgressChangedEvent is fired.
            If MyUpload.BytesTotal > 0 Then
                ProgressBarTransfered.Value = (MyUpload.BytesTransfered / MyUpload.BytesTotal) * 100

                Dim MyHelper As New SprightlySoftAWS.S3.Helper
                LabelBytesTransfered.Text = MyHelper.FormatByteSize(MyUpload.BytesTransfered) & " / " & MyHelper.FormatByteSize(MyUpload.BytesTotal)
            End If
        End If
    End Sub


End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions