Smack FileTransfer Library

Hello Everyone,

I am a software engineer working on the development of an inhouse instant messaging client for my employer using the smack 2.2.0 api. I am in need of some assistance using the FileTranfer classes which are included in 2.2.0. I have followed the documentation included with the source, but I cannot seem to get the file transfer to work. The OutputStream created by the sendfile() method in the OutgoingFileTransfer class is always null nomatter what I try. Here is an example of how I am attempting the transfer.

//This creates a new XMPPConnection

XMPPConnection connection = Session.getInstance().getConnection();

// This creates the file transfer manager

FileTransferManager manager = new FileTransferManager(connection);

// Opens a file selection dialog

FileDialog fd = new FileDialog(new Shell(), SWT.NONE);

// Sets the text of the file selection dialog

fd.setText(“Select the File to Send:”);

// Creates a String to hold the path to the choosen file

String filePath = fd.open();

// Create the outgoing file transfer with the recipients username and qualifier

transfer = manager.createOutgoingFileTransfer(recipient

  • “/spark”);

//If the filePath is not null then start the file transfer

if (filePath != null) {

//filesize here is a temporary variable holding the size of the test file I am sending

transfer.sendFile(filePath, filesize, “Check This Out!”);

}else{//Else print an error message

//This is temporary will be replaced with a prompt later.

System.out.print(“You left the filePath blank!”);

}

Any help will be greatly appreciated!

Thanks,

Robert

Just FYI here is the example straight from the documentation for this class. It uses a different method which only takes a file and file description but there is another method that takes a filelocation, filesize and description which I used in my example. I have tried to use all thee methods that the class offers with no success.

Examples

In this example we can see how to send a file:

// Create the file transfer manager

FileTransferManager manager = new FileTransferManager(connection);

// Create the outgoing file transfer

OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer ("romeo@montague.net");

// Send the file

transfer.sendFile(new File(“shakespeare_complete_works.txt”), “You won’'t believe this!”);

Thanks again

Robert

Hi,

are you using the proxy service? I did disable it and restart Wifi and the file was transfered immediately. With the proxy running I had no luck.

You should also add XMPPConnection.DEBUG_ENABLED=true; to your code to debug this further and maybe also the client should open the debug window.

LG

Thanks LG, I’'ll give that a try.

Robert

My Wildfire error.log shows when using the 7777 proxy:

[org.jivesoftware.wildfire.filetransfer.FileTransferProxy.handleIQ(FileTransferP roxy.java:119)

] Error activating connection

java.lang.IllegalArgumentException: Transfer doesn’'t exist or is missing parameters

at org.jivesoftware.wildfire.filetransfer.ProxyConnectionManager.activate(ProxyCon nectionManager.java:220)

at org.jivesoftware.wildfire.filetransfer.FileTransferProxy.handleIQ(FileTransferP roxy.java:116)

at org.jivesoftware.wildfire.filetransfer.FileTransferProxy.process(FileTransferPr oxy.java:287)

at org.jivesoftware.wildfire.IQRouter.handle(IQRouter.java:215)

at org.jivesoftware.wildfire.IQRouter.route(IQRouter.java:96)

at org.jivesoftware.wildfire.PacketRouter.route(PacketRouter.java:65)

at org.jivesoftware.wildfire.net.SocketReader.processIQ(SocketReader.java:396)

at org.jivesoftware.wildfire.net.ClientSocketReader.processIQ(ClientSocketReader.j ava:50)

at org.jivesoftware.wildfire.net.SocketReader.readStream(SocketReader.java:264)

at org.jivesoftware.wildfire.net.SocketReader.run(SocketReader.java:119)

at java.lang.Thread.run(Unknown Source)

I tried turning off the Proxy but that did not work. I added the XMPP_DEBUG=true to my code. The debug info and warnings are listed below. It doesn’'t mean a whole lot to me but I am new to the world jabber and instant messenger development.

Debug Tab

2006.04.12 17:19:17 Logging off rstone@phantom/1144879834259 on org.jivesoftware.wildfire.net.SocketConnection@11402c4 socket: Socket[addr=/192.168.1.100,port=4093,localport=5222] session: org.jivesoftware.wildfire.ClientSession@6765 status: 3 address: rstone@phantom/1144879834259 id: 932f8bd2 presence:

(ConnectionPool.java:108)

] Failed to create new connections on startup. Attempt 0 of 3

java.sql.SQLException: The database is already in use by another process: org.hsqldb.persist.NIOLockFile@c798e4a6[file =C:\Program Files\Wildfire\embedded-db\wildfire.lck, exists=true, locked=false, valid=false, fl =null]: java.lang.Exception: checkHeartbeat(): lock file is presumably locked by another process.

at org.hsqldb.jdbc.Util.sqlException(Unknown Source)

at org.hsqldb.jdbc.jdbcConnection.(XMPPServer.java:142)

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)

at java.lang.reflect.Constructor.newInstance(Unknown Source)

at java.lang.Class.newInstance0(Unknown Source)

at java.lang.Class.newInstance(Unknown Source)

at org.jivesoftware.wildfire.starter.ServerStarter.start(ServerStarter.java:88)

at org.jivesoftware.wildfire.starter.ServerStarter.main(ServerStarter.java:49)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at com.exe4j.runtime.LauncherEngine.launch(Unknown Source)

at com.exe4j.runtime.WinLauncher.main(Unknown Source)

2006.04.12 17:03:32 [org.jivesoftware.wildfire.net.SocketReader.run(SocketReader.java:161)

] Connection closed before session established

Socket[addr=/192.168.1.100,port=3619,localport=5269]

2006.04.12 17:04:02 [org.jivesoftware.wildfire.net.SocketReader.run(SocketReader.java:161)

] Connection closed before session established

Socket[addr=/192.168.1.100,port=3651,localport=5269]

Info Tab

2006.04.10 21:00:40 Admin console listening at:

http://phantom:9090

https://phantom:9091

2006.04.12 07:27:00 Publish-Subscribe domain: pubsub.phantom

2006.04.12 07:27:00 Started server (unencrypted) socket on port: 5269

2006.04.12 07:27:00 Started plain (unencrypted) socket on port: 5222

2006.04.12 07:27:01 Started SSL (encrypted) socket on port: 5223

2006.04.12 07:27:01 Multi User Chat domain: conference.phantom

2006.04.12 07:27:01 Wildfire 2.6.0

2006.04.12 07:27:03 Admin console listening at:

http://phantom:9090

https://phantom:9091

2006.04.12 16:22:51 Publish-Subscribe domain: pubsub.phantom

2006.04.12 16:22:51 Started server (unencrypted) socket on port: 5269

2006.04.12 16:22:51 Started plain (unencrypted) socket on port: 5222

2006.04.12 16:22:52 Started SSL (encrypted) socket on port: 5223

2006.04.12 16:22:52 Multi User Chat domain: conference.phantom

2006.04.12 16:22:52 Wildfire 2.6.0

2006.04.12 16:22:54 Admin console listening at:

http://phantom:9090

https://phantom:9091

2006.04.12 16:24:50 Wildfire stopped

2006.04.12 16:24:55 Server halted

2006.04.12 16:25:07 Publish-Subscribe domain: pubsub.phantom

2006.04.12 16:25:07 Started server (unencrypted) socket on port: 5269

2006.04.12 16:25:07 Started plain (unencrypted) socket on port: 5222

2006.04.12 16:25:08 Started SSL (encrypted) socket on port: 5223

2006.04.12 16:25:08 Multi User Chat domain: confrence.phantom

2006.04.12 16:25:08 Wildfire 2.6.0

2006.04.12 16:25:09 Admin console listening at:

http://phantom:9090

https://phantom:9091

2006.04.12 16:57:12 Publish-Subscribe domain: pubsub.phantom

2006.04.12 16:57:12 Started server (unencrypted) socket on port: 5269

2006.04.12 16:57:12 Started plain (unencrypted) socket on port: 5222

2006.04.12 16:57:12 Started SSL (encrypted) socket on port: 5223

2006.04.12 16:57:12 Multi User Chat domain: confrence.phantom

2006.04.12 16:57:12 Wildfire 2.6.0

2006.04.12 16:57:14 Admin console listening at:

http://phantom:9090

https://phantom:9091

2006.04.12 17:01:41 Multi User Chat domain: confrence.phantom

2006.04.12 17:01:41 Started server (unencrypted) socket on port: 5269

2006.04.12 17:01:41 Started plain (unencrypted) socket on port: 5222

2006.04.12 17:01:42 Started SSL (encrypted) socket on port: 5223

2006.04.12 17:01:42 Publish-Subscribe domain: pubsub.phantom

2006.04.12 17:01:42 Wildfire 2.6.0

2006.04.12 17:01:44 Admin console listening at:

http://phantom:9090

https://phantom:9091

I also printed out the status and file progress the results are below

The progress is -1.0

The amount of the file that has been written is => -1

I looped through the whole time I was connected and it is always -1 and -1.0

The other weird thing is that I tried to get the OutputStream, create an array of bites from the OutputStream, and print out the array of bites using a for loop. The result of this is that the OutputStream apears to be null and that does not make sense to me. I am giving it a valid file I can process the file (i.e. copy to another location and the likes) but I cannot seem to send it over the messenger.

I am really at a loss. If any of this means anything to you please enlighten me.

Thank a lot.

Robert

The way the method operates that you are calling is completely different then I think what you are expecting. The method call you are using is this:

OutputStream sendFile(String fileName, long fileSize, String description)

/code

If you check out the javadocs on this method you will see this:

“This method handles the negotiation of the file transfer and the stream, it only returns the created stream after the negotiation has been completed.”

It returns the OutputStream, I don’'t see in your code snippet where you are saving that OutputStream or what you are doing with it. But, if you want to use that method you need to read the stream on your own and save it to the file. progress and file transfer status on the OutgoingFileTransfer object are not updated after that point.

In other words, the method you are calling is completly different then the one in the docs, which is what all the documentation you quoted is based off of. The former does not handle the file transfer whereas the latter does on its own background thread.

Hope that helps,

Alex

I actually have tried all three available methods. The one I posted in the forum I actually was using to test and see what was being sent to the recipient. I got the stream and tried to save it to an array of bites and then print the array of bites in a for loop. I just didn’'t include that part in the snipplet here is the loop.

try {

OutputStream out = transfer.sendFile(filePath, filesize,“Check This Out!”);

byte[]array = new byte[50];

out.write(array);

for(int i = 0; i < array.length - 1; i++){

System.out.print(array[i]);

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

The results of this was that the OutputStream was null which really confused me because I know the file I am sending in is valid. No matter what I try I am still getting the same error. If I try to transfer from my client to spark, spark says"There was an error during file transfer." Even if I use the first method: transfer.sendFile(file, description); I still get the same error. All of my error logs are in the posts above. If you can be of further assistance AWenckus I would really appreciate it.

Thanks,

Robert

Hey Robert,

You use an output stream to write data, IE send a file. So, you need to write the data from an input stream, namely your file, to the outputstream returned from transfer#sendFile().

The array will be empty because you are not populating it with any data.

I think the better method to use in your case would be the one specified in the documentation. Which handles the reading from your file and writing to the outputstream for you.

Thanks,

Alex

Alex,

I realize my mistake in that posted example but the fact remains that even if I use the example in the documentation I still am not able to send the file. Here is the code I wrote using the example in the documentation.

try {

// Creates a new XMPPConnection

XMPPConnection connection = Session.getInstance()

.getConnection();

XMPPConnection.DEBUG_ENABLED=true;

// Creates the file transfer manager

FileTransferManager manager = new FileTransferManager(connection);

// Create the outgoing file transfer

transfer = manager.createOutgoingFileTransfer(participant

  • “/messenger”);

// Sets the ResponseTimeout to 1

transfer.setResponseTimeout(1000);

// Opens a file selection dialog

FileDialog fd = new FileDialog(new Shell(), SWT.NONE);

// Sets the text of the file selection dialog

fd.setText(“Select the File to Send:”);

// Creates a String to hold the path to the choosen file

String filePath = fd.open();

if (filePath != null) {

File file = new File(filePath);

transfer.sendFile(file, “Here is the file”);

while (!transfer.isDone()) {

System.out.println("The amount of the file that has been written is => "

  • transfer.getAmountWritten());

if (transfer.getStatus().equals(Status.ERROR)) {

System.out.println("ERROR!!! "

  • transfer.getError());

} else {

System.out.println("The status is " + transfer.getStatus().toString());

System.out.println("The progress is " + transfer.getProgress());

}

}

} else {

System.out.println(“Catch this bugger later.”);

}

} catch (XMPPException e) {

// print the caught exception

e.printStackTrace();

}

I know that I am being a bit of a pest and for that I apologize. I am just new to this and am trying to learn. The problem is that even with the above code I still get the same error. If there is an error in the way I have written the code above please let me know.

Robert

My first question is why are you changing the response timeout to 1? My second question is can you post the Raw Sent and the Raw Recieved from the Smack debugger?

Thanks,

Alex

Alex,

As far as setting the response timeout to 1. I did that because it was never timing out at all until I manualy set it. I left it sit for about 20 minutes and it was still stuck on negotiating transfer.

As far as the sent and received are concerned they are both 0.

Other than the setting of the response timeout was there anything else incorrect about the code that you could see?

I really appreciate all of your help! I have been working on this almost all day and have been quite frustrated.

Thanks,

Robert

I can’‘t really see too much else wrong with your code other then the response time. If anything you would likely want to increase that to 10 * 1000, or, 10 seconds. When you say sent and recieved are both 0, what do you mean? There are no sent or recieved packets? If there aren’'t then there is something likely fundamentally wrong, here is how mine looks after two file transfers:

Raw sent:

Just so everyone knows I fixed the problem with my file transfer. My main problem was that my stream.close(); for both my input and output streams were never getting called. Anyway an example of the correct code is listed below.

try {

// Creates a new XMPPConnection

XMPPConnection connection = Session.getInstance()

.getConnection();

// Sets debug enabled true

XMPPConnection.DEBUG_ENABLED=true;

// Creates the file transfer manager

FileTransferManager manager = new FileTransferManager(connection);

// Create the outgoing file transfer with qualifier (i.e / clientname)

transfer = manager.createOutgoingFileTransfer(participant

  • “/” + messenger);

// Opens a file selection dialog

FileDialog fd = new FileDialog(new Shell(), SWT.NONE);

// Sets the text of the file selection dialog

fd.setText(“Select the File to Send:”);

// Creates a String to hold the path to the choosen file

String filePath = fd.open();

sf = new File(filePath);

long fileSize = sf.length();

String fileName = sf.getName();

if (filePath != null) {

try {

// output is an OutputStream declared as a global variable.

/* Note that transfer.sendFile(fileName, fileSize, description);

returns an OutputStream */

output = transfer.sendFile

(fileName, fileSize , “”);

//This is an InputStream declared as a global variable.

input = new FileInputStream(sf);

int i;

while((i = in.read())!= -1){

out.write((byte)i);

}

} catch (FileNotFoundException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

//Close the streams when finished

in.close();

out.close();

}

} catch (XMPPException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

P.S. I forgot to mention that the disabling of the file server proxy in wildfire was correct also. I went back into my wildfire server now that my code is working and re-enabled the file server proxy and the file transfer quit working then I disabled it again and file transfer worked again. So, just another note for everyone. At least in wildfire under /server settings/file transfer settings/ make sure that proxy service is disabled or file transfers Will Not Work!

Cheers,

Robert

I think that you are experiencing another issue with proxy transfers. Is your wildfire server on one of the machines doing the file transfer?

Thanks,

Alex

Alex,

Yes, you are correct. So moral of the story is turn the proxy off if you are trying to test on the same machine that you are running the server on. Sorry for the confusion, but as I said before I am new to messaging.

Robert

Hi Alex,

my setup is: EclipseSmacksimple_program + Wifi on one computer and Spark to receive the file on another computer.

Does it make sense that the file transfer using the proxy fails or is this a bug of the file transfer proxy listening on port 7777?

LG

Hey LG,

It should work if you change the port on wifi to use a different one, if it doesn’'t, let me know. I personally have been able to get it to work with both clients and wifi running through my IDE on one computer. It may also be affected if you have Spark running on the same machine.

Cheers,

Alex