使用 smack 'XMPPError: service-unavailable - cancel' 传输文件失败

Posted

技术标签:

【中文标题】使用 smack \'XMPPError: service-unavailable - cancel\' 传输文件失败【英文标题】:Failed to transfer file using smack 'XMPPError: service-unavailable - cancel'使用 smack 'XMPPError: service-unavailable - cancel' 传输文件失败 【发布时间】:2017-07-11 09:51:06 【问题描述】:

我正在尝试使用 smack 扩展库 4.2.0 传输文件,但无法成功传输文件。当我尝试传输文件时,这是我得到的错误

org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPP error reply received from 252615100006@server/Smack: XMPPError: service-unavailable - cancel

即使对等点 00006 在线,但我不知道为什么我会收到对等点的错误

这是我传输文件的代码

public void sendImageMessage(String sendTo, String imagePath) throws XmppStringprepException 
        FileTransferManager manager = FileTransferManager.getInstanceFor(mConnection);
        EntityBareJid jid = JidCreate.entityBareFrom(sendTo);
        EntityFullJid entityFullJid = JidCreate.entityFullFrom(jid+"/Smack");
        Domainpart domainpart = entityFullJid.getDomain();
//        Log.d(TAG ," JID Domain "+entityFullJid.do)

        OutgoingFileTransfer outgoingFileTransfer = manager.createOutgoingFileTransfer(entityFullJid);
        File file = new File(imagePath);
        try 
            outgoingFileTransfer.sendFile(file, file.getName());
         catch (SmackException e) 
            e.printStackTrace();
        
        while (!outgoingFileTransfer.isDone()) 
            if (outgoingFileTransfer.getStatus().equals(FileTransfer.Status.error)) 
                System.out.println("ERROR!!! " + outgoingFileTransfer.getError());
             else if (outgoingFileTransfer.getStatus().equals(FileTransfer.Status.cancelled)
                    || outgoingFileTransfer.getStatus().equals(FileTransfer.Status.refused)) 
                System.out.println("Cancelled!!! " + outgoingFileTransfer.getError());
            
            try 
                Thread.sleep(1000L);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
        if (outgoingFileTransfer.getStatus().equals(FileTransfer.Status.refused) || outgoingFileTransfer.getStatus().equals(FileTransfer.Status.error)
                || outgoingFileTransfer.getStatus().equals(FileTransfer.Status.cancelled)) 
            System.out.println("refused cancelled error" + outgoingFileTransfer.getError().toString());
         else 
            System.out.println("Successfully_SEND");
        

非常感谢任何帮助和指导

编辑: 我用户 spark 客户端使用我的服务器传输文件,它成功传输了文件。所以问题不在于服务器,我认为它不在客户端的代码中

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,我研究了这节并以这种方式解决了。

许多人使用 "/Smack" 或 "/Resource" 作为 jid 中的资源部分,但这可以通过其他方式完成。

资源路径随着用户的每次改变而改变。假设我们要向该用户发送图像: “user1@mydomain”

您必须在此 jid 中添加“/Resource”或 “/Smack” 部分,它变为: user1@mydomain/资源

user1@mydomain/Smack

但是资源路径会随着存在而改变,因此您必须遵循每个存在更改来更新资源路径。 最好的方法是让用户存在是在名册监听器中,在 presencheChanged() 方法中你得到最后一个用户资源部分,如下所示:

Roster roster=getRoster();
roster.addRosterListener(new RosterListener() 
                @Override
                public void entriesAdded(Collection<Jid> addresses) 
                    Log.d("entriesAdded", "ug");
                    context.sendBroadcast(new Intent("ENTRIES_ADDED"));
                

                @Override
                public void entriesUpdated(Collection<Jid> addresses) 
                    Log.d("entriesUpdated", "ug");
                

                @Override
                public void entriesDeleted(Collection<Jid> addresses) 
                    Log.d("entriesDeleted", "ug");
                

                @Override
                public void presenceChanged(Presence presence) 
                    Log.d("presenceChanged", "ug");
                    //Resource from presence
                    String resource = presence.getFrom().getResourceOrEmpty().toString();
                    //Update resource part for user in DB or preferences
                    //...
                
            );

资源字符串将是一些生成的字符串,例如 "6u1613j3kv" 并且 jid 将变为: user1@mydomain/6u1613j3kv

这意味着您必须像这样创建传出传输:

EntityFullJid jid = JidCreate.entityFullFrom("user1@mydomain/6u1613j3kv"); 
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(jid)

你的情况是这样的:

EntityBareJid jid = JidCreate.entityBareFrom(sendTo);
EntityFullJid entityFullJid = JidCreate.entityFullFrom(jid + resource);

resource 是监听器中存在的资源部分。

这就是我在 smack 和 Openfire 上解决文件传输问题的方法。

另外提到你必须在你的 Openfire 服务器中添加以下属性:

xmpp.proxy.enabled - true
xmpp.proxy.externalip - MY_IP_ADDRESS
xmpp.proxy.port -7777

顺便提一下,我使用的是 Openfire 4.0.2 和 Smack 4.2.2。

这也可以很容易地配置,只需将资源设置为

XMPPTCPConnectionConfiguration.Builder .

喜欢

XMPPTCPConnectionConfiguration.Builder configurationBuilder = 
XMPPTCPConnectionConfiguration.builder(); 

configurationBuilder.setResource("yourResourceName");

【讨论】:

以上是关于使用 smack 'XMPPError: service-unavailable - cancel' 传输文件失败的主要内容,如果未能解决你的问题,请参考以下文章

Android Smack 4.2:“XMPPError: feature-not-implemented - cancel”(错误)

XMPPError:未找到项目 - 取消

XMPPError connected to chat.facebook.com (Permission denied) login to facebook chat with asmack

android中的XMPP连接使用smack

使用 Smack 4.1.3 注册用户

如何在安卓上使用 Smack