Recently, we needed a solid file sender/receiver system developed in .NET to be used with several service bus systems such as Azure Microsoft Service Bus, Active MQ, Active MQ – Artemis, and Rabbit MQ – who all support AMQP and code technologies like C# and .NET. . I found Sean Feldman’s plugin for doing this and adjusted it. The main difference in functionality that was needed was the that the file was to be placed temporarily in a fileshare (in-house because of security requirements) and not an Azure Blob share. We ended up making the .NET Standard LargeFileServiceBusCourier NuGet package.
To test it I installed a local Windows Apache Active MQ – Artemis Message Queue broker with docker. This requires Docker for Windows to be installed.
docker run -it --rm -p 8161:8161 -p 61616:61616 vromero/activemq-artemis
Alternatively, you can open an azure account with Microsoft and create a queue namespace there.
.NET Standard plugin for sending and receiving large files through an AMQP 1.0 service bus, using the claim check enterprise pattern, not sending the files through the services, but utilising a creation of a file on a file drive, which is written and read by the package. It can be configured to use a file store, and is supposed to be able to be used with any service bus which supports the AMQP 1.0 format.
Service Bus Selected, installed and configured.
Currently tested on Active MQ - Artemis and Microsoft Azure Service Bus.
The solution uses a queue called FilePrint, you can create this in your service. Some bus implementations can dynamically create a Queue on request.
If you have an azure portal account on portal.azure.com create a service bus namespace and a queue called FilePrint. Fetch the information from the servicesbus namespace from the shared access policies both the endpoint address and Primary key. The connections string should end up looking something like this if you are using a websocket connection: "wss://RootManageSharedAccessKey:2rAcHDFSxT%2BDSJCageQSSuGjOpxv6v%2FfN9TIiuSv4Y%3D@pdfprint.servicebus.windows.net:443/$servicebus/websocket";
or something like this, if you are using an amqp 1.0 connection: amqps://RootManageSharedAccessKey:2rAcHDFSxT%2BDSJCageQSSuGjOpxv6v%2FfN9TIiuSv4Y%3D@pdfprint.servicebus.windows.net/
Prerequisites: Docker installed.
Download and install Active MQ - Artemis, with docker open a command prompt and write:
docker pull alexcheng/activemq-artemis
docker run -d --hostname my-artemis --name fileprint -p 5673:5672 -p 1884:1883 -p 61617:61616 -p 5446:5445 -p 8162:8161 -e ARTEMIS_USERNAME=guest -e ARTEMIS_PASSWORD=guest alexcheng/activemq-artemis
You can logon to the local artemis installation with guest/guest on the address: http://localhost:8162
And you can use the connection string: "amqp://guest:guest@localhost:5673" to access the artemis server.
You must create a Queue named FilePrint and also with this address and the ANYCAST routing selected.
Depending on which service bus you want to use, you nead to create a connection string so that the servicebus that you are using is utilised. Please read the specific solution for the servicebus of your choice.
You also have to choose which shared drive that you want the solution to place the intermediate claim check files in. For instance c:\temp
In order to use the package in your c# project, you can install the package by writing
Install-Package LargeFileServiceBusCourier -Version 1.0.5
To send a file you need to define the address which is the connection string and a fileStoragePath. Below is a connection string for the Microsoft Azure Service Bus using the websocket connection.
private readonly string address = "wss://RootManageSharedAccessKey:2rAcHDFSX%2BDSJCageQQSSuGjOpxv6v%2FfN9TIiuSv4Y%3D@pdfprint.servicebus.windows.net:443/$servicebus/websocket";
private readonly string fileStoragePath = @"C:\temp";
public async Task DispatchFileToServiceBus()
{
TransportFileInformation transportFileInformation = new TransportFileInformation
{
DocumentTitle = "document test",
FileType = FileType.PDF,
ReferenceNumber = "Reference_Number",
OriginalName = "pdfSampleFilePath",
Originator = "Me",
TransactionName = "TransportFileInformation"
};
FileInformationWithByteArray fileInformationWithByteArray = new FileInformationWithByteArray(transportFileInformation, FileToByteArray(pdfSampleFilePath));
await ServiceBusManager.DispatchFile(fileInformationWithByteArray, address, fileStoragePath);
}
To receive the file you must define a function which will handle the received packages.
public bool ByteArrayToFile(string fileName, byte[] byteArray)
{
try
{
using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
fs.Write(byteArray, 0, byteArray.Length);
return true;
}
}
catch
{
return false;
}
}
private void MessageReceived(IReceiverLink receiverLink, FileInformationWithByteArray fileInformationWithByteArray, Message messageReceived)
{
var testing = fileInformationWithByteArray.ByteArray;
if (testing != null)
{
try
{
string[] paths = { @"C:\temp\", fileInformationWithByteArray.FileInformation.TransactionName + ".pdf" };
string fullPath = Path.Combine(paths);
ByteArrayToFile(fullPath, testing);
receiverLink.Accept(messageReceived);
}
catch
{
receiverLink.Reject(messageReceived);
}
}
else
{
receiverLink.Reject(messageReceived);
}
}
Which is passed to the following call:
await ServiceBusManager.StartReceivingFromReceiverLink(MessageReceived, address);
Voila!!
Comments