Android Question how to Resume file transfer using AsyncStreams

Asim A Baki

Active Member
Licensed User
Longtime User
Assuming 2GB file is currently transferred over AsyncStreams
then a disconnection occurred after 1GB
I need to have a chance to resume the file after Reconnecting

Any solution for AsyncStreams?
 

Asim A Baki

Active Member
Licensed User
Longtime User
Are you sending the file with WriteStream?
I'm sending the file from DotNet using the function below

B4X:
       Private Sub sendFile(fileToSend As String, Targetfilepath As String, Client As Socket)
            Try
                Dim adler As New Adler32()

                Using fs As New FileStream(fileToSend, FileMode.Open, FileAccess.Read, FileShare.Read)
                    Dim name As Byte() = Encoding.UTF8.GetBytes((Targetfilepath))
                    Dim Stream = New NetworkStream(Client)
                    Dim bw As New BinaryWriter(Stream)
                    'send the first message which is the file name
                    bw.Write(name.Length)
                    bw.Write(name)
                    'send the stream message
                    bw.Write(STREAM_PREFIX)
                    Dim size As Long = New FileInfo(fileToSend).Length
                    bw.Write(size) 'Send the total file length
                    Dim written As Long = 0
                    Dim buffer As Byte() = New Byte(BufferSize) {}
                    While written < size
                        Dim count As Integer = fs.Read(buffer, 0, Math.Min(CLng(size - written), buffer.Length))
                        Stream.Write(buffer, 0, count)
                        adler.Update(buffer, 0, count)
                        written += count
                    End While
                    bw.Write(adler.Value)
                    'log("File sent successfully.")
                End Using
            Catch e As Exception
                'mDelRemoveDisconnected()


            End Try
            'Dim mi As MethodInvoker = Sub() btnSend.Enabled = Not btnConnect.Enabled
            'Me.BeginInvoke(mi)
        End Sub
 
Upvote 0

Asim A Baki

Active Member
Licensed User
Longtime User
It will be simpler to use AsyncStreams in non-prefix mode and manage the file transfer yourself. The client can send the number of bytes that were already received and the server can then skip over the part that was already sent.

Is it possible to tell AsyncStreams Prefix mode not to write in temp file and write directly the the final filename ? or at least get the name of the temp file currently transfered?

So I can manage to apend to the preexisting file
 
Upvote 0

Asim A Baki

Active Member
Licensed User
Longtime User
It will be simpler to use AsyncStreams in non-prefix mode and manage the file transfer yourself. The client can send the number of bytes that were already received and the server can then skip over the part that was already sent.

I've Done so, but I'm facing a problem with receiving the data as I got many commands in the same event and I need to split the commands

LENGTHPREFIX-DATA
LENGTHPREFIX-DATA

sometimes I receive the data
LENGTHPREFIX
DATA
LENGTHPREFIX-DATA

So I need to capture only the desired length from the buffer to process each message/File separately
 
Upvote 0

Asim A Baki

Active Member
Licensed User
Longtime User
In that case you should use prefix mode.
Finally I got it working by eliminating AsyncStreams, and use only inputStream, and OutputStream captured from Socket

I'm facing a problem in the following code, that the ReadBytes Blocks execution even if the function was called in a new thread

how to resolve this issue?
B4X:
    Dim bc As ByteConverter
    bc.LittleEndian=True
    Dim Buffer (65535) As Byte, Read As Int
    Try
    Dim inStream As InputStream=client.InputStream
    Dim count As Int
       
    Dim LengthBytes(4) As Byte,Length As Int
    count=inStream.ReadBytes (LengthBytes,0,4)
    If count=-1 Then Return True
   
   
    Length =bc.IntsFromBytes(LengthBytes)(0)
   
   
    Dim TypeB(1) As Byte
    inStream.ReadBytes (TypeB,0,1)

    Select Case TypeB(0)
        Case 67'Command
            Dim CommandBytes(Length-1) As Byte
            inStream.ReadBytes (CommandBytes,0,Length-1)
           
            Dim nCommandData As String=BytesToString(CommandBytes , 0, Length-1,"utf8")
            ProcessCommand(nCommandData)
       
        Case 70'File
            '------------- Read FileName -------------
            Dim FileNameBytes(Length-1) As Byte
            inStream.ReadBytes (FileNameBytes,0,Length-1)
            currentFile= BytesToString(FileNameBytes , 0, Length-1,"utf8")
            '-----------------------------------------
           
            '------------ Read File Length as long 8 bytes
            Dim FileLengthBytes(8) As Byte
            inStream.ReadBytes (FileLengthBytes,0,8)
           
            Dim FileLength As Long =bc.LongsFromBytes(FileLengthBytes)(0)
           
            Dim outFile As OutputStream = File.OpenOutput(MainHelper.ActiveOfflineDirectory, currentFile, True)
           
            '------------ Read File Data -------------
            '-------- Write File Data
           
            Do While Read < FileLength
               
                count=inStream.ReadBytes(Buffer,0,Min((FileLength-Read),Buffer.Length ))
                   
                'Write To File

   
                outFile.WriteBytes(Buffer, 0, count)

                'Increment CRC32
                progressValue = 100 * Read / FileLength
                UpdateProgress(False)
                Read=Read+count
                DoEvents
            Loop
           
            Dim ChecksumBytes (8) As Byte
            inStream.ReadBytes(ChecksumBytes,0,8)
            outFile.Close
           
           
        End Select
    Catch
        Log(LastException)
        ConnectSocket
    End Try


      Return False
 
Upvote 0

Asim A Baki

Active Member
Licensed User
Longtime User
The only correct way to work with network streams is by using AsyncStreams.
Thanks,
So to be able to do so please inform me how to read a fixed number of bytes from asyncstreams buffer to do something like this
B4X:
Dim CommandBytes(Length-1) As Byte
            inStream.ReadBytes (CommandBytes,0,Length-1)
          
            Dim nCommandData As String=BytesToString(CommandBytes , 0, Length-1,"utf8")
            ProcessCommand(nCommandData)
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
So to be able to do so please inform me how to read a fixed number of bytes from asyncstreams buffer to do something like this
You cannot read fixed number of bytes from AsyncStreams. If you have implemented the prefix protocol correctly then it will work automatically. Otherwise NewData will be raised whenever there is data available.

However it is very simple to send files. Maybe this example will help you: https://www.b4x.com/android/forum/threads/74320/#content
 
Upvote 0
Top