openfire文件传输
我已经看到许多人在asmack ( Android构建环境和smack补丁)中为文件传输而苦苦挣扎。 经过一些调试成功后,我在Openfire服务器上尝试了相同的库。 因此,我想分享我的问题和解决方案。 我发现问题出在字节流主机中,它尝试连接到错误的主机以使用字节流启动文件传输。 如果您尚未正确配置文件传输代理,则它将选择127.0.0.1或localhost或任何内部配置的host / ip作为字节流主机,在android中这不被视为用于通信的正确ip。 但是请稍候,为什么它可以与具有相同服务器的桌面客户端正常工作。 原因是桌面客户端可以轻松识别此ips,并可以使用它打开套接字进行文件传输。
以下讨论中使用的变量名称是:
名称 | 含义 |
myHost | 运行Openfire的计算机的主机名。 |
user1 @ myHost | 文件传输发起者用户 |
user2 @ myHost | 文件的收件人 |
如何知道为字节流选择了哪个主机:(以下XML在发送和接收到文件传输启动器时显示。)
- 首先查询其他客户端以获取有关支持功能的信息:
发送:
<iq id='x1ixz-13' to='user2@myHost/Smack' type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'></query>
</iq>
收到:
<iq id='x1ixz-13' to='user1@myHost/Smack' type='result' from='user2@myHost/Smack'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<!—some other items -->
<feature var='http://jabber.org/protocol/bytestreams'/>
<!—some other items -->
</query>
</iq>
在这里您可以知道客户端另一端是否支持字节流文件传输。 如果您在响应中看到类似上面的xml,则在另一端受支持,您可以继续。
- 查询服务器中的迪斯科项目:
发送:
<iq id='x1ixz-14' to='myHost' type='get'>
<query xmlns='http://jabber.org/protocol/disco#items'></query>
</iq>
收到:
<iq type='result' id='x1ixz-14' from='myHost' to='user1@ myHost /Smack'>
<query xmlns='http://jabber.org/protocol/disco#items'>
<!—some other items -->
<item jid='proxy. myHost ' name='Socks 5 Bytestreams Proxy'/>
<!—some other items -->
</query>
</iq>
在这里,您将收到服务器支持的不同项目的各种项目,例如文件传输代理,搜索服务,会议服务……我们应该寻找的项目是“ Socks 5 Bytestreams Proxy”。
- 请求有关代理的更多信息
发送:
<iq id='x1ixz-19' to='proxy. myHost ' type='get'>
<query xmlns='http://jabber.org/protocol/bytestreams'/>
</iq>
收到:
<iq type='result' id='x1ixz-19' from='proxy. myHost ' to='user1@ myHost /Smack'>
<query xmlns='http://jabber.org/protocol/bytestreams'>
<streamhost jid='proxy. myHost ' host=' myHost ' port='7777'/>
</query>
</iq>
在此, <streamhost>中的主机是文件传输的密钥。 您必须确保可以从您的Android手机访问此主机。 它不应类似于localhost,127.0.0.1或公司外部无法访问的任何公司内部配置的服务器。 它必须是可公开访问的IP地址或主机。
要配置适当的代理,请在Openfire中添加/更改以下3个属性:
- xmpp.proxy.enabled – true
- xmpp.proxy.port – 7777
- xmpp.proxy.externalip – [可公开访问的主机或IP]
文件传输的代码:
FileTransferManager manager = new FileTransferManager(connection);
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer('usre2@myHost/Smack');
File file = new File(filenameWithPath);
try {
transfer.sendFile(file, 'test_file');
} catch (XMPPException e) {
e.printStackTrace();
}
while(!transfer.isDone()) {
if(transfer.getStatus().equals(Status.error)) {
System.out.println('ERROR!!! ' + transfer.getError());
} else if (transfer.getStatus().equals(Status.cancelled)
|| transfer.getStatus().equals(Status.refused)) {
System.out.println('Cancelled!!! ' + transfer.getError());
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
|| transfer.getStatus().equals(Status.cancelled)){
System.out.println('refused cancelled error ' + transfer.getError());
} else {
System.out.println('Success');
}
和文件代码接收:
FileTransferManager manager = new FileTransferManager(connection);
manager.addFileTransferListener(new FileTransferListener() {
public void fileTransferRequest(final FileTransferRequest request) {
new Thread(){
@Override
public void run() {
IncomingFileTransfer transfer = request.accept();
File mf = Environment.getExternalStorageDirectory();
File file = new File(mf.getAbsoluteFile()+'/DCIM/Camera/' + transfer.getFileName());
try{
transfer.recieveFile(file);
while(!transfer.isDone()) {
try{
Thread.sleep(1000L);
}catch (Exception e) {
Log.e('', e.getMessage());
}
if(transfer.getStatus().equals(Status.error)) {
Log.e('ERROR!!! ', transfer.getError() + '');
}
if(transfer.getException() != null) {
transfer.getException().printStackTrace();
}
}
}catch (Exception e) {
Log.e('', e.getMessage());
}
};
}.start();
}
});
还配置ProviderManager以正确地解码/解析字节流和其他所需的xml:
ProviderManager.getInstance().addIQProvider('query','http://jabber.org/protocol/bytestreams', new BytestreamsProvider());
ProviderManager.getInstance().addIQProvider('query','http://jabber.org/protocol/disco#items', new DiscoverItemsProvider());
ProviderManager.getInstance().addIQProvider('query','http://jabber.org/protocol/disco#info', new DiscoverInfoProvider());
我使用的asmack库是asmack-jse-buddycloud.jar。
参考:我们的JCG合作伙伴 Harsh Raval在harryjoy博客上使用asmack和Openfire在android中进行文件传输 。
翻译自: https://www.javacodegeeks.com/2012/08/android-file-transfer-with-asmack-and.html
openfire文件传输