Dropbox API Upload Wait for asynchronous function - vb.net

guys
I'm having difficulty with the Dropbox API in uploading.
I have a list of files, and in each pass of the for I call the function that uploads:
Public Function Upload(ByVal ArquivoOrigem As String, ByVal ArquivoDestino As String)
Try
Dim fileStream As FileStream = New FileStream(ArquivoOrigem, FileMode.Open)
Me.CtrlTask = Task.Run(Function() Upload_Executar(fileStream, ArquivoDestino))
Me.CtrlTask.Wait()
Catch ex As Exception
End Try
End Function
Private Async Function Upload_Executar(ByVal fileStream As FileStream, ByVal ArquivoDestino As String) As Task
Me.ArquivoUploadIs = False
Try
Dim numChunks As Integer = CInt(Math.Ceiling(CDbl(fileStream.Length) / Me.chunkSize))
Dim buffer As Byte() = New Byte(Me.chunkSize - 1) {}
Dim sessionId As String = Nothing
Console.WriteLine("Chunk upload file...")
Console.WriteLine("fileStream.Length: " + fileStream.Length.ToString())
Console.WriteLine("chunkSize: " + Me.chunkSize.ToString())
Console.WriteLine("numChunks: " + numChunks.ToString())
For idx = 0 To numChunks - 1
Dim Porc1 As Integer = 0
Dim Porc2 As Integer = 0
Porc1 = CInt((idx / numChunks) * 100)
Porc2 = idx * Me.chunkSize
Console.WriteLine("Posicao: " + idx.ToString() + " / Total: " + numChunks.ToString() + " / Porc1: " + Porc1.ToString() + " / Total Transferido: " + FormatBytes(Porc2) + " / Tamanho Total: " + FormatBytes(fileStream.Length))
Dim byteRead = fileStream.Read(buffer, 0, Me.chunkSize)
Using memStream As MemoryStream = New MemoryStream(buffer, 0, byteRead)
If idx = 0 Then
Console.WriteLine("memStream.Length: " + memStream.Length.ToString())
Console.WriteLine("UploadSessionStartAsync")
Dim result = Await Dbx.Files.UploadSessionStartAsync(False, memStream)
Console.WriteLine(result)
sessionId = result.SessionId
Console.WriteLine("sessionId: " + sessionId)
Else
Dim cursor As UploadSessionCursor = New UploadSessionCursor(sessionId, CULng((Me.chunkSize * idx)))
If idx = numChunks - 1 Then
Console.WriteLine("UploadSessionFinishAsync")
Dim CtrlUp = Await Dbx.Files.UploadSessionFinishAsync(cursor, New CommitInfo(ArquivoDestino), memStream)
If CtrlUp.Id <> "" Then
Me.ArquivoUploadIs = True
End If
Else
Console.WriteLine("UploadSessionAppendV2Async")
Await Dbx.Files.UploadSessionAppendV2Async(cursor, body:=memStream)
End If
End If
End Using
Next
Catch ex As Exception
ShowMsgError(ex)
End Try
End Function
And I call her through the task, using "wait" to wait for the submission to finish before going to the next file:
Upload("C:\Arq1.pdf", "/Arq1.pdf");
Upload("C:\Arq2.pdf", "/Arq2.pdf");
Upload("C:\Arq3.pdf", "/Arq3.pdf");
Upload("C:\Arq4.pdf", "/Arq4.pdf");
However, while the upload is done the application is stuck.
To test put a thread, however, this causes all files in my list to be sent at the same time and I want to send one, wait for it to finish and then send the next one.
Does anyone have any suggestions?

You should avoid using .Wait as it can cause deadlocks.
Public Async Function Upload(ByVal ArquivoOrigem As String, ByVal ArquivoDestino As String) As Task
Try
Dim fileStream As FileStream = New FileStream(ArquivoOrigem, FileMode.Open)
Await Upload_Executar(fileStream, ArquivoDestino))
Catch ex As Exception
End Try
End Function
Await Upload("C:\Arq1.pdf", "/Arq1.pdf");
Await Upload("C:\Arq2.pdf", "/Arq2.pdf");
Await Upload("C:\Arq3.pdf", "/Arq3.pdf");
Await Upload("C:\Arq4.pdf", "/Arq4.pdf");

Related

how to use ZoomNet DownloadFileAsync

I'm using a Nuget package Jericho /ZoomNet, trying to download a zoom recording (mp4) [winform App]
I'm not sure how the DownloadFileAsync() works to save the File from the Stream, I keep getting task cancelled exception
Can you point to any similar examples ?
UPDATE
So i talked to the Author of the package,
he made a beta release to download large files more efficiently, and also showed me you can add your own client object to control the timeout according to file size, also using the ConfigureAwait(False) was necessary.
Dim myHttpClient = New HttpClient() With {
.Timeout = TimeSpan.FromMinutes(10) }
Dim azoomClient = New ZoomClient(connectionInfo,
myHttpClient)
Dim sourceStream = Await
azoomClient.CloudRecordings.DownloadFileAsync(fdownloadFileName, ct).ConfigureAwait(False)
Using outStream = File.OpenWrite(DestFileName)
sourceStream.CopyTo(outStream)
End Using
This is the code I've tried
Private azoomClient = New ZoomClient(connectionInfo)
Dim fdownloadFileName As String = "c:\zoomrec1.mp4"
Dim ct As New Threading.CancellationToken
Dim sourceStream As Stream
sourceStream = Await azoomClient.CloudRecordings.DownloadFileAsync(fdownloadFileName, ct).ConfigureAwait(False)
DumpStream(sourceStream, DestFileName)
Private Async Function DumpStream(ByVal outStream As Stream, ByVal outputFileName As String) As Task
Try
' Dump the contents of a stream to a file
outStream.Flush()
Dim SavePos As Long = outStream.Position ' Save the original position in the stream
outStream.Seek(0, SeekOrigin.Begin)
Dim f As Stream = File.OpenWrite(outputFileName)
CopyStream(outStream, f)
outStream.Position = SavePos ' Go back to the original postion in the stream
f.Close()
Catch ex As Exception
MessageBox.Show("Error:DumpStream()>" & ex.Message)
End Try
End Function
Public Shared Sub CopyStream(ByVal input As Stream, ByVal output As Stream)
Try
' Copy the contents of one stream to another stream
Dim buf As Byte() = New Byte(8 * 1024 - 1) {} ' A buffer for storing data while copying
Dim len As Integer
len = input.Read(buf, 0, buf.Length)
While len > 0
output.Write(buf, 0, len)
len = input.Read(buf, 0, buf.Length)
End While
Catch ex As Exception
MessageBox.Show("Error:CopyStream()>" & ex.Message)
End Try
End Sub
'''
i can get the download url filename with this call,
'''
Dim apiKey = "abc" Dim apiSecret = "123"
Dim connectionInfo As New JwtConnectionInfo(apiKey, apiSecret)
Dim v As Object = azoomClient.CloudRecordings.GetRecordingInformationAsync(MeetingID)
Dim modelsRecording = Await v
downloadFileName = CStr(modelsRecording.RecordingFiles.Where(Function(z)
z.FileType = Models.RecordingFileType.Video)(0).DownloadUrl)
'''
I updated the code above with a working solution.

Unable to cast object of type 'System.Object' to type (MyClass) Vb.Net

I am using this code to store the object of my class "Device" to Object but I am getting the "system.invalidcastexception" Exception. I cast it in the same way in other classes and there it worked but here it is not working
Public Class Device
Inherits MainDevice
Private TestData As New SortedList(Of Integer, DataVPAA)
Public Sub New(ByVal version As String, ByVal System As String, ByVal IdNumber As UInteger, ByVal Serial As String)
DataVersion = version
SystemVersion = System
Serial_Number = Serial
IdentNumber = IdNumber
This is where i am getting the Error
Dim obj As Object
obj = LoadXml(GetType(Device), Path)
If obj Is Nothing Then
' Some Logic Here
Else
Dim dev As New Device
dev = CType(obj, Device) '**system.invalidcastexception**
Me.TestData = dev.TestData
' Some Logic Here
End If
End Sub
End Class
Load Function
Function LoadXML(ByVal DeviceType As Type, ByVal Path As String) As Object
Dim obj As New Object
Dim XMLFilePath As String
Dim xmlreader As XmlReader
If Me.GetType = GetType(ABCDevice) Or Me.GetType = GetType(CVDevice) Or Me.GetType = GetType(CV2Device) Then
XMLFilePath = Path + "\" + strIdentNr + "_" + Serial_Number + ".xml"
Else
XMLFilePath = Path + "\" + IdentNumber.ToString + "_" + Serial_Number + ".xml"
End If
'Check if File exists
If File.Exists(XMLFilePath) Then
Dim fs As New FileStream(XMLFilePath, FileMode.Open, FileAccess.Read)
xmlreader = XmlReader.Create(fs)
Try 'Try to deserialize to object
Dim xml_deserializer As New Serialization.XmlSerializer(DeviceType)
If xml_deserializer.CanDeserialize(xmlreader) Then
obj = xml_deserializer.Deserialize(xmlreader)
End If
Catch ex As Exception
MessageBox.Show("XML Deserializer Error: " + ex.Message)
End Try
fs.Close()
Return obj
Else : Return Nothing
End If
End Function
I tried to cast it with different methods like directcast and others but i am getting the same exception.
You can make the LoadXml generic and always return the type you want. Such as
Function LoadXml(Of T)(path As String) As T
Dim obj As T = Nothing
Dim XMLFilePath As String
If Me.GetType = GetType(ABCDevice) Or Me.GetType = GetType(CVDevice) Or Me.GetType = GetType(CV2Device) Then
XMLFilePath = path + "\" + strIdentNr + "_" + Serial_Number + ".xml"
Else
XMLFilePath = path + "\" + IdentNumber.ToString + "_" + Serial_Number + ".xml"
End If
'Check if File exists
If File.Exists(XMLFilePath) Then
Using fs As New FileStream(XMLFilePath, FileMode.Open, FileAccess.Read)
Using reader = XmlReader.Create(fs)
Try 'Try to deserialize to object
Dim xml_deserializer As New Serialization.XmlSerializer(GetType(T))
If xml_deserializer.CanDeserialize(reader) Then
obj = xml_deserializer.Deserialize(reader)
End If
Catch ex As Exception
MessageBox.Show("XML Deserializer Error: " + ex.Message)
End Try
End Using
End Using
End If
Return obj
End Function
Dim dev = LoadXml(Of Device)("path")
Now dev is guaranteed to be a Device. If it's Nothing, it failed

vb.net progress bar value throws ArgumentOutOfRange exception while uploading a file using await async

i can not update a ProgressBar value,i tried also
Convert.ToInt32(Bytes as long).But,it does not worked.
i'm using Progress (of integer).
'Button OnClick
Public Shared s3client As AmazonS3Client
Public Shared myProgress As Progress(Of Integer)
Public Shared Bytes As Double
Public Shared myProgress As Progress(Of Integer)
Public Shared bucketName As String = "S3BucketName"
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim AllowedFiles As List(Of String) = New List(Of String)
Try
Dim TheSize As Long
Dim TotalSize As Long
For Each file In AllowedFiles
TheSize = Long.Parse((My.Computer.FileSystem.GetFileInfo(file).Length))
TotalSize += TheSize
Next
Select Case TotalSize
Case Is >= 1099511627776
Bytes = CDbl(TotalSize / 1099511627776) 'TB
Case 1073741824 To 1099511627775
Bytes = CDbl(TotalSize / 1073741824) 'GB
Case 1048576 To 1073741823
Bytes = CDbl(TotalSize / 1048576) 'MB
Case 1024 To 1048575
Bytes = CDbl(TotalSize / 1024) 'KB
Case 0 To 1023
Bytes = TotalSize ' bytes
Case Else
Bytes = 0
'Return ""
End Select
ProgForm2.CPBar1.Value = 0
ProgForm2.CPBar1.Minimum = 0
ProgForm2.CPBar1.Maximum = Convert.ToInt32(Bytes)
Dim result As DialogResult = MessageBox.Show("Selected " & TotalFiles & " files have " & CalculateSize.ToString & "" & SizeType, "in total Size", MessageBoxButtons.OKCancel, MessageBoxIcon.Information)
If result = DialogResult.OK And TextBox1.Text IsNot "" = True Then
myProgress = New Progress(Of Integer)(AddressOf ReportProgress)
Foldername=Textbox1.Text
For Each file In AllowedFiles
Try
ProgForm2.Show()
Await AddFileToRootFolderAsync(file, bucketName, Foldername, myProgress)
TheSize = Long.Parse(My.Computer.FileSystem.GetFileInfo(file).Length)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
ProgForm2.CPBar1.Text = ProgForm2.CPBar1.Value.ToString + "/" + Form2.CPBar1.Maximum.ToString
Next
ProgForm2.CPBar1.Value = ProgForm2.CPBar1.Maximum
If ProgForm2.CPBar1.Value = ProgForm2.CPBar1.Maximum Then
ProgForm2.CPBar1.Text = "Task Completed"
ProgForm2.Button1.Show()
End If
Else
Exit Sub
End if
End Sub
'file uploading function
Public Async Function AddFileToFolderAsync(FileName As String, bucketName As String, folderName As String, ByVal myProgress As IProgress(Of Integer)) As Task
Try
If AmazonS3Util.DoesS3BucketExistV2(s3client, bucketName) Then
Dim Checkresult = FolderCheck(bucketName, folderName) /'Folder Exist or Not
If Checkresult = True Then
Dim keyname As String = "" 'destination path(s3 bucket folder)
Dim filepath As String = FileName 'current file's local fullpath
Dim fname As String = Path.GetFileName(FileName) 'filename
If Not folderName.EndsWith("/") Then
keyname += folderName & "/"
keyname += fname 'bucket's target folder /fname (eg:folder/subfolder/file.mp4)
Else
keyname += fname 'bucket's target folder /fname (eg:folder/subfolder/file.mp4)
End If
Dim fileTransferUtility = New TransferUtility(s3client)
Dim fileTransferUtilityRequest = New TransferUtilityUploadRequest With {
.BucketName = bucketName,
.FilePath = filepath,
.StorageClass = S3StorageClass.Standard,
.ServerSideEncryptionMethod = ServerSideEncryptionMethod.None,
.PartSize = 6291456,
.Key = keyname,
.ContentType = "*.*"}
AddHandler fileTransferUtilityRequest.UploadProgressEvent,
Sub(sender As Object, e As UploadProgressArgs)
Dim percent As Integer = Convert.ToInt32(e.TransferredBytes) //e.TransferredBytes as long
myProgress.Report(percent)
End Sub
Await fileTransferUtility.UploadAsync(fileTransferUtilityRequest)
Else
MessageBox.Show(folderName + " folder does not exist")
End If
Else
MessageBox.Show(bucketName + " Bucket does not exist")
End If
Catch ex As AmazonS3Exception
MessageBox.Show(ex.Message + " Upload task canceled.")
Catch ex As Exception
MessageBox.Show(ex.Message + " Upload task canceled.")
End Try
End Function
Public Sub ReportProgress(ByVal myInt As Integer)
Form2.CPBar1.Value += myInt
Form2.CPBar1.Text = Form2.CPBar1.Value.ToString + "/" + Form2.CPBar1.Maximum.ToString
End Sub
i am stucked into this,can't know what i missed.I want to progress Bytes which is transferred to target folder in my progressbar.for example, the file size is 1gb(1073741824 bytes) then how can i set Progressbar maximum value=1073741824 and progressbar value + =transferredbytes.
It seems that when you want to calculate the Maximum value, you've token into account the value of the TotalSize through the Select-Case mechanism and hence, scaled it based on its range. But in the ReportProgress, the myInt input integer is directly added to the progressbar value. I think your Select-Case should be implemented in the ReportProgress as well.
Edit 1:
Let's assume that TotalSize = 109951162777. Right? Hence, Byte = 1 and the progressbar's maximum value is equal to 1 (i.e., 1 TB). Then, in the ReportProgress function you must first divide myInt (which is in bytes) by 109951162777 to make it a TB value (e.g., 0.5 TB) and then update the progressbar's value. If you do not do so, myInt will exceed the int32 limit and errors occur. Am I right?
Therefore, you have to know that which case is selected in the Select-Case statement and the TotalSize is divided by which number? I recommend to modify the Button1_Click function as:
Dim divider as long
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim AllowedFiles As List(Of String) = New List(Of String)
Try
Dim TheSize As Long
Dim TotalSize As Long
For Each file In AllowedFiles
TheSize = Long.Parse((My.Computer.FileSystem.GetFileInfo(file).Length))
TotalSize += TheSize
Next
Select Case TotalSize
Case Is >= 1099511627776
divider = 1099511627776 'TB
Case 1073741824 To 1099511627775
divider = 1073741824 'GB
Case 1048576 To 1073741823
divider = 1048576 'MB
Case 1024 To 1048575
divider = 1024 'KB
Case 0 To 1023
divider = 1 ' bytes
Case Else
Bytes = 0
divider = 1
'Return ""
End Select
Bytes = CDbl(TotalSize / divider) 'always between 0 and 1
ProgForm2.CPBar1.Value = 0
ProgForm2.CPBar1.Minimum = 0
ProgForm2.CPBar1.Maximum = Convert.ToInt32(Bytes)
Dim result As DialogResult = MessageBox.Show("Selected " & TotalFiles & " files have " & CalculateSize.ToString & "" & SizeType, "in total Size", MessageBoxButtons.OKCancel, MessageBoxIcon.Information)
If result = DialogResult.OK And TextBox1.Text IsNot "" = True Then
myProgress = New Progress(Of Integer)(AddressOf ReportProgress)
Foldername=Textbox1.Text
For Each file In AllowedFiles
Try
ProgForm2.Show()
Await AddFileToRootFolderAsync(file, bucketName, Foldername, myProgress)
TheSize = Long.Parse(My.Computer.FileSystem.GetFileInfo(file).Length)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
ProgForm2.CPBar1.Text = ProgForm2.CPBar1.Value.ToString + "/" + Form2.CPBar1.Maximum.ToString
Next
ProgForm2.CPBar1.Value = ProgForm2.CPBar1.Maximum
If ProgForm2.CPBar1.Value = ProgForm2.CPBar1.Maximum Then
ProgForm2.CPBar1.Text = "Task Completed"
ProgForm2.Button1.Show()
End If
Else
Exit Sub
End if
End Sub
and the ReportProgress as follows:
Form2.CPBar1.Value += myInt / divider ‘to normalize myInt to [0,1]
Form2.CPBar1.Text = Form2.CPBar1.Value.ToString + "/" + Form2.CPBar1.Maximum.ToString
Hope this solves the problem.

Function is trying to convert to boolean somewhere

I have a function in Winforms VB.Net and when I call this function I keep getting an exception saying I can't convert a String to Boolean. However, I can't see where it is trying to convert anything to a Boolean. Code is below
Public Async Function UploadArrayToDropbox(client As DropboxClient, folder As String, fileName As String, fileArray As ArrayList) As Task
Dim stream As New MemoryStream
Using r As StreamWriter = New StreamWriter(stream)
For i As Integer = 0 To fileArray.Count - 1
r.WriteLine(fileArray(i).ToString)
Next
r.Flush()
stream.Position = 0
Using rd As StreamReader = New StreamReader(stream)
Dim response = Await client.Files.UploadAsync(Convert.ToString(folder & Convert.ToString("/")) & fileName, WriteMode.Overwrite.Instance, rd.ReadToEnd)
rd.Close()
End Using
r.Close()
End Using
End Function
Dim response = Await client.Files.UploadAsync(Convert.ToString(folder & Convert.ToString("/")) & fileName, WriteMode.Overwrite.Instance, rd.ReadToEnd)
Should be
Dim response = Await client.Files.UploadAsync(Convert.ToString(folder & Convert.ToString("/")) & fileName, WriteMode.Overwrite.Instance, body:=rd)
From Maurice ;)

Getting Cannot access a closed file error

I use the following code to iterate a collection of files that I need to copy from one folder to another. It works fine when the source file exist, but when it does not exist I get
System.ObjectDisposedException: Cannot access a closed file. at System.IO.__Error.FileNotOpen() at System.IO.FileStream.get_Position()
What am I missing here?
For Each itm In listOfFiles
Try
If File.Exists(itm.SourcePath + itm.FileName) Then
Dim cf As New FileStream(itm.SourcePath + itm.FileName, FileMode.Open)
Dim ct As New FileStream(itm.DestinationPath + itm.FileName, FileMode.Create)
Dim len As Long = cf.Length - 1
Dim buffer(1024) As Byte
Dim byteCFead As Integer
While cf.Position < len
byteCFead = (cf.Read(buffer, 0, 1024))
ct.Write(buffer, 0, byteCFead)
fileCopyProgressBar.BeginInvoke(New Action(Sub() fileCopyProgressBar.Value = CInt(cf.Position / len * 100)))
End While
ct.Flush()
ct.Close()
cf.Close()
itm.FileExsits = True
Else
itm.FileExsits = False
End If
Catch ex As Exception
log.Error(ex.Message & " (unc)")
End Try
Next
Try calculating value before putting it in the action. You should also dispose of the streams when done with them
For Each itm In listOfFiles
Try
If File.Exists(itm.SourcePath + itm.FileName) Then
Using cf As New FileStream(itm.SourcePath + itm.FileName, FileMode.Open)
Using ct As New FileStream(itm.DestinationPath + itm.FileName, FileMode.Create)
Dim len As Long = cf.Length - 1
Dim buffer(1024) As Byte
Dim byteCFead As Integer
Dim percentage As Integer
While cf.Position < len
byteCFead =(cf.Read(buffer, 0, 1024))
ct.Write(buffer, 0, byteCFead)
percentage = CInt(cf.Position / len * 100)
fileCopyProgressBar.BeginInvoke(New Action(Sub() fileCopyProgressBar.Value = percentage))
End While
ct.Flush()
ct.Close()
cf.Close()
End Using
End Using
itm.FileExsits = True
Else
itm.FileExsits = False
End If
Catch ex As Exception
log.Error(ex.Message & " (unc)")
End Try
Next