How to send files larger than 4 MB by using Microsoft Message Queuing (198686)



The information in this article applies to:

  • Microsoft Message Queue Server (MSMQ) 1.0
  • Microsoft Message Queuing 2.0
  • Microsoft Message Queuing 3.0

This article was previously published under Q198686

SUMMARY

Many of the features of Microsoft Message Queuing make it natural for building fault tolerant file transfer utilities: cost-based routing, fault tolerance, compression, and encryption. One of the difficulties of creating a file transfer solution is the limitation that Message Queuing messages can be no larger than 4 MB. This article illustrates how to break up large files, assign them to a byte array, and send them through Message Queuing messages.

MORE INFORMATION

To run the sample code, follow these steps:
  1. Start Visual Basic and create a new Standard EXE project.
  2. From the Project menu, click References, and then select Microsoft Message Queue Object Library from the list.
  3. Double-click the Form1 dialog, paste the following code, and then press F5 to run the sample.Sample Code
    Option Explicit
    
    Private Sub Form_Load()
       ' Message Queuing can not send messages larger than 4MB. In order to
       ' send larger messages, we must break the large messages
       ' into chunks, send the chunks as individual messages, and
       ' reassemble them at the destination.
          
       Dim chunksize As Long ' Holds a value to specify the maximum number of bytes per chunk.
       chunksize = 4096000   ' Defines the max number of bytes per chunk (roughly 3MB in this case)
       
       Dim qi As New MSMQQueueInfo ' Object to hold information about the destination queue.
       Dim q As MSMQQueue          ' The destination queue object.
       Dim msg As New MSMQMessage  ' The message that will be sent to the queue (a file chunk in this case).
       
       ReDim buff(19) As Byte      ' Byte array.
       Dim strfilename As String   ' File name of the file to be sent.
       Dim Chunks As Long          ' Number of total chunks.
       Dim Semichunk As Long ' Size of the last chunk (which will be smaller than chunksize -- the remainder).
       Dim i As Long ' Index for the loop to send complete chunks.
    
       qi.PathName = ".\msmqxfer" ' Change this to your destination queue.
       On Error GoTo ErrorCreateQueue
       qi.Create    ' Create the queue if it does not exist.
       On Error GoTo 0
        On Error GoTo ErrorOpenQueue
       Set q = qi.Open(MQ_SEND_ACCESS, 0) ' Open the queue for send access.
        On Error GoTo 0
       
       strfilename = "c:\boot.ini"        ' Change this to the file that you wish to send.
    
       Open strfilename For Binary As #1  ' Open the file to be sent to the queue.
       
       ' Determine the number of chunks that will need to be sent and their sizes.
       Chunks = LOF(1) \ chunksize  - 1     ' Determine the total number of complete chunks that will need to be sent for this file.
       Semichunk = LOF(1) Mod chunksize - 1 ' Determine the size of the last chunk of the file (the remainder).
       buff(0) = Chunks + (IIf(Semichunk > 0, 1, 0))  ' buff(0) contains the number of total (complete + any remainder) chunks.
       
       msg.CorrelationId = buff ' The message that is being sent will contain info regarding the total number of messages.
       
       ReDim buff(chunksize)    ' buff will now be used as a temp storage space for holding a message chunk before it is sent to the queue.
       ' Send as many chunks of chunksize as you can.
       For i = 1 To Chunks
            Get #1, , buff      ' Load one chunk from the source file.
                    msg.Label = strfilename ' All messages containing chunks of this file will have the same label.
    msg.AppSpecific = i      ' i is included in the message so that the receiver will understand the order to use when reassembling chunks.
            msg.Body = buff  ' Load the chunk from the buffer into the message body.
            msg.Send q       ' Send this message to the queue.
       Next
       
       ' Now send any leftover portion that was not large enough to fill a complete chunk.
       ReDim buff(Semichunk)         ' Resize the buffer to hold the last partial chunk.
       Get #1, , buff ' Load the chunk from the source file.
          msg.Label = strfilename ' All messages containing chunks of this file will have the same label.
    msg.AppSpecific = i + 1       ' Setting the sequence number.
       msg.Body = buff ' Load the chunk from the buffer into the message body.
       msg.Send q ' Send the partial chunk.
       
        ' Done sending the file
       q.Close                       ' Close the queue.
       Close #1                      ' Close the file.
    
    MsgBox "Successfully sent file " & strfilename & ", " & (chunksize * Chunks) + Semichunk & " bytes."
    
        Exit Sub
        
    ErrorCreateQueue:
       If Err.Number = -1072824315 Then
       Resume Next
       Else
       MsgBox "Error while creating the queue!  You may not have permission to create queues on this computer, or the queue could be owned by another user.\n" & Err.Number & " -- " & Err.Description
     End If
     Exit Sub
        
    ErrorOpenQueue:
        MsgBox "Error while opening the queue!  The queue may be owned by another user.\r" & Err.Number & " -- " & Err.Description
        Exit Sub
    End Sub
    					
NOTE: Many shortcuts were made in this sample code. Two notable examples are the lack of error handling and the fact that the code will fail (with the error "Overflow") with files that broken into over 255 pieces (since this is stored in one element of the byte array).

REFERENCES

For more information on the Message Queuing object library, see the Message Queuing SDK guide.

Modification Type:MajorLast Reviewed:4/20/2005
Keywords:kbhowto KB198686