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个属性:

  1. xmpp.proxy.enabled – true
  2. xmpp.proxy.port – 7777
  3. 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文件传输