Sub PrepareDownload(data As Map)
    Dim filename As String = data.GetDefault("filename", "")
    Dim session As String = data.GetDefault("session", "")
    Dim ackRequired As Boolean = data.GetDefault("ackRequired", True)
 
    ' Define a command string for acknowledgment or logging purposes.
    Dim cmd As String = "downloadFile"
    ' Check if the file exists before proceeding.
    If filename <> "" And File.Exists(baseDir, filename) Then
        Dim su As StringUtils
  
        ' Initialize RandomAccessFile to read the specified file.
        Dim raf As RandomAccessFile
        raf.Initialize(baseDir, filename, False)
  
        ' Obtain the file size for chunking and progress calculations.
        Dim fileSize As Long = raf.Size
        Log("File size: " & fileSize)
  
        ' Set the chunk size in bytes (for instance, 10 MB here).
        Dim chunkSize As Int = 10 * 1024 * 1024
  
        ' This offset tracks our position in the file as we read in chunks.
        Dim offset As Long = 0
  
        ' First pass: calculate the MD5 hash of the entire file (also in chunks to prevend memory exceptions).
        Dim jo As JavaObject
        jo.InitializeStatic("java.security.MessageDigest")
        jo = jo.RunMethod("getInstance", Array("MD5"))
  
        ' Loop through the file in chunks to update the MD5 digest.
        Do While offset < fileSize
            Dim remaining As Long = fileSize - offset
            Dim actualSize As Int = chunkSize
            If remaining < chunkSize Then actualSize = remaining
      
            Dim buffer(actualSize) As Byte
            raf.ReadBytes(buffer, 0, actualSize, offset)
      
            ' Update the MD5 digest with the current chunk's bytes.
            jo.RunMethod("update", Array(buffer))
      
            ' Advance the offset by the number of bytes read.
            offset = offset + actualSize
        Loop
  
        ' Retrieve the final MD5 hash as a byte array, then encode it in Base64.
        Dim finalHash() As Byte = jo.RunMethod("digest", Null)
        Dim fileHash As String = su.EncodeBase64(finalHash)
  
        ' Reset offset for the second pass where we actually send chunks.
        offset = 0
  
        ' Calculate the total number of chunks for reference.
        Dim totalChunks As Int = Ceil(fileSize / chunkSize)
  
        ' Second pass: read and publish file data chunk by chunk.
        Do While offset < fileSize
            Dim remaining As Long = fileSize - offset
            Dim actualSize As Int = chunkSize
            If remaining < chunkSize Then actualSize = remaining
      
            Dim buffer(actualSize) As Byte
            raf.ReadBytes(buffer, 0, actualSize, offset)
      
            ' Increment offset before we build the MQTT message.
            offset = offset + actualSize
      
            ' Encode the current chunk's data in Base64 for transmission.
            Dim chunkBase64 As String = su.EncodeBase64(buffer)
      
            ' Build a JSON map containing chunk data and metadata.
            Dim mp As Map
            mp.Initialize
            mp.Put("filename", filename)
            mp.Put("data", chunkBase64)
            mp.Put("chunkIndex", (offset / chunkSize) - IIf(remaining < chunkSize, 0, 0))
            mp.Put("totalChunks", totalChunks)
            mp.Put("hash", fileHash)
            mp.Put("session", session)
      
            ' Convert the map to a JSON string, then to a byte array for publishing.
            Dim Payload() As Byte = mp.As(JSON).ToCompactString.GetBytes("UTF8")
            mqtt.Publish(Tools.deviceID & "/download", Payload)
            Log("publish chunk #" & (offset / chunkSize))
        Loop
  
        ' Close the file reader once all chunks are sent.
        raf.Close
  
        ' Optionally send an acknowledgment if required.
        If ackRequired Then
            SendAcknowledgment(session, cmd, CreateMap("filename": filename), True, "")
        End If
    Else
        ' If the file does not exist, optionally send a negative acknowledgment.
        If ackRequired Then
            SendAcknowledgment(session, cmd, CreateMap("filename": filename), False, "File not found")
        End If
    End If
End Sub