Filetransfer Client
Introduction
The SwiftMQ Filetransfer client is an easy-to-use client to transfer files of unlimited size between JMS clients and a SwiftMQ Router. It uses an existing JMS connection and can be easily integrated with any JMS application.
The client API consists of only 3 classes:
Class | Package | Description |
|---|---|---|
| com.swiftmq.filetransfer | Provides the Filetransfer client. |
| com.swiftmq.filetransfer | A filetransfer exception class. |
| com.swiftmq.filetransfer | Provides information about the progress of a file transfer. |
Samples
There are several example programs provided under the SwiftMQ distribution's directory "samples/filetransfer". Please have a look!
Protecting Files
A file can be protected by a password that needs to be specified during receive. A file can also be declared as private. Links to private files are not returned from a query, rather the link needs to be known.
File Expiration
Similar to JMS messages, a file can have an expiration which is specified in milliseconds. The file is automatically deleted after it has expired.
Maximum Downloads
The maximum number of downloads can be specified for a file. The file is automatically deleted after this number has been reached.
Message Properties and Selectors
The following message properties are automatically set during send:
Property | Type | Value |
|---|---|---|
|
| The JMS user who sent the file. |
|
| The original filename |
|
| File size in bytes |
|
| The absolute expiration time in ms (since 01/01/1970) |
|
| The digest type, e.g. "SHA1". |
|
| The absolute store time in ms (since 01/01/1970) |
|
| The number of downloads after which the file will be deleted. |
|
| The current number of downloads. |
The sender can add arbitrary custom JMS message properties to a file, e.g. by setting an "orderid" property to mark a file containing a purchase order.
In addition to the Filetransfer properties listed above, all custom properties can be used in a message selector, too. For example, if custom property "orderid" was set as a custom property and one wants to get all PDF files for a particular order id, a query might look like this:
orderid = 12345 and JMS_SWIFTMQ_FT_FILENAME like '%.pdf'
To select all zip-files of a particular customerId range which are bigger than 1 MB, use this selector:
JMS_SWIFTMQ_FT_FILENAME like '%.zip'
and customerid between 10000 and 11500
and JMS_SWIFTMQ_FT_SIZE > 1024 * 1024
Sending Files
The most basic usage of a Filetransfer object to send files is to create it, set the file to send, send and close it:
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
String link = filetransfer.withFile(file).send();
filetransfer.close();
A Filetransfer object can be used to send multiple files sequentially but can not be used by multiple threads (use a dedicated Filetransfer object per thread, see Filetransfer samples):
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
for (int i=0; i < files.length; i++)
filetransfer.withFile(file[i]).send();
filetransfer.close();
Various other settings can be applied in a builder style fashion:
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
String link = filetransfer.withDigestType("SHA1")
.withFileIsPrivate(isPrivate)
.withPassword("Cheers")
.withFile(file)
.send();
filetransfer.close();
In addition to a bunch of message properties that are automatically set from the Filetransfer, custom message properties can be added to each file that can be used to select them through a message selector:
Map props = new HashMap();
props.put("orderid", orderId);
props.put("customerid", customerId);
props.put("documenttype", docType);
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
String link = filetransfer.withDigestType("SHA1")
.withFileIsPrivate(isPrivate)
.withPassword("Cheers")
.withProperties(props)
.withFile(file)
.send();
filetransfer.close();
A ProgressListener can be used too:
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
String link = filetransfer.withFile(file).send(new ProgressListener()
{
public void progress(String filename, int chunksTransferred,
long fileSize, long bytesTransferred,
int transferredPercent)
{
System.out.println(" " + filename + ": " + chunksTransferred +
" chunks, "+ bytesTransferred + " of " + fileSize +
" transferred (" + transferredPercent + "%)");
}
});
filetransfer.close();
Receiving Files
The most basic usage of a Filetransfer object to receiving a file is to create it with a link, set the output file, receive and close it:
Filetransfer.create(connection, link)
.withFile(file)
.receive()
.close();
To delete the file at the file cache after receive, call:
Filetransfer.create(connection, link)
.withFile(file)
.receive()
.delete()
.close();
One can also use the original filename. In that case the output directory needs to be specified:
Filetransfer.create(connection, link)
.withOutputDirectory(outDir)
.withOriginalFilename(true)
.receive()
.delete()
.close();
The password needs to be specified if file is protected:
Filetransfer.create(connection, link)
.withOutputDirectory(outDir)
.withOriginalFilename(true)
.withPassword("Cheers")
.receive()
.delete()
.close();
A ProgressListener can be used too:
Filetransfer.create(connection, link)
.withOutputDirectory(outDir)
.withOriginalFilename(true)
.receive(new ProgressListener()
{
public void progress(String filename, int chunksTransferred,
long fileSize, long bytesTransferred,
int transferredPercent)
{
System.out.println(" " + filename + ": " + chunksTransferred +
" chunks, "+ bytesTransferred + " of " + fileSize +
" transferred (" + transferredPercent + "%)");
}
}).delete().close();
Querying Links
There are 2 ways to get a link to a file:
The sending client sends it to the receiving client by using JMS (e.g. sends a JMS
TextMessage). This is required for private files.The receiving client queries the file cache.
To query a file cache, any existing or a new Filetransfer object can be used:
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
List<String> result = filetransfer.query();
filetransfer.close();
final CountDownLatch countDownLatch = null;
if (result != null && result.size() > 0)
{
countDownLatch = new CountDownLatch(result.size());
for (int i = 0; i < result.size(); i++)
{
final String link = result.get(i);
executorService.execute(new Runnable()
{
public void run()
{
transfer(link); // Uses a dedicated Filetransfer object to receive a file
countDownLatch.countDown();
}
});
}
}
if (countDownLatch != null)
countDownLatch.await();
A JMS message selector can be used to select specific files:
Filetransfer filetransfer = Filetransfer.create(connection, routerName, cacheName);
List<String> result = filetransfer.withSelector(selector).query();
filetransfer.close();
// ....
Querying Properties
This functionality has been removed in SwiftMQ 13.2.0 due to XStream dependency.