Failed to transfer file using smack 'XMPPError: service-unavailable - cancel'

ぐ巨炮叔叔 提交于 2020-05-29 09:50:06

问题


I'm trying to transfer file using smack extension library 4.2.0 but couldn't able to successfully transfer file. When i try to transfer file this is the error I'm getting

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

Even though the peer 00006 is online but I don't why I'm receiving error from the peer

This is my code to transfer file

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");
        }

Any help and guidance is much appreciated

Edit : I user spark client to transfer files using my server it susseccfully tranfered the file. So the problem is not with server I thin't it's in code on client side.


回答1:


I had same problem, I investigated the stanza and solved it this way.

Many people use "/Smack" or "/Resource" as resource part in jid, but that can be done another way.

Resource path is changing with every presence changed of user. Lets say we want to send image to this user: "user1@mydomain"

You must add "/Resource" or "/Smack" part to this jid and it become this: user1@mydomain/Resource

user1@mydomain/Smack

But resource path is changing with presence so you must follow every presence change to update resource path. Best way is to get user presence is in roster listener and in presencheChanged() method you get last user resource part like this:

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
                    //...
                }
            });
}

Resource string will be some generated string like "6u1613j3kv" and jid will become: user1@mydomain/6u1613j3kv

That means that you must create your outgoing transfer like this:

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

In your case like this:

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

Where resource is resourcepart from Presence in listener.

And that is how i have solved my problem with file transfer on smack and Openfire.

Also to mention you must add following properties in your Openfire server:

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

Just to mention, I am using Openfire 4.0.2 and Smack 4.2.2.

Also this can be configured the easy way, just set the resource on

XMPPTCPConnectionConfiguration.Builder .

like

XMPPTCPConnectionConfiguration.Builder configurationBuilder = 
XMPPTCPConnectionConfiguration.builder(); 

configurationBuilder.setResource("yourResourceName");


来源:https://stackoverflow.com/questions/45031111/failed-to-transfer-file-using-smack-xmpperror-service-unavailable-cancel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!