使用Smack 4.2.4在jabb3r.org发送文件遇service-unavailable错误求助
首先,你遇到的XMPPError: service-unavailable - wait错误,核心原因是你强制启用了IBB(In-Band Bytestreams)传输方式,但jabb3r.org服务器并不支持IBB服务。而Xabber和Chat Secure能成功发送文件,是因为它们使用了**HTTP Upload(XEP-0363)**协议,也就是你看到的proxy.hot-chilli.net:5281/upload这个上传端点。
接下来我会给你具体的修复步骤和代码调整方案:
1. 关闭IBB强制设置
你的代码里设置了FileTransferNegotiator.IBB_ONLY = true;,这会让Smack只尝试用IBB传输,直接忽略其他更合适的方式(比如HTTP Upload)。先把这行代码删掉,让Smack自动协商最优的传输机制。
2. 改用HTTP Upload实现文件发送
Smack 4.2.4已经支持XEP-0363 HTTP Upload,你需要使用HttpUploadManager来处理文件上传,而不是原来的FileTransferManager。以下是调整后的代码:
public void send(String id, String path) throws XmppStringprepException { // 初始化服务发现管理器,确保支持HTTP Upload特性 ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); if (sdm == null) { sdm = new ServiceDiscoveryManager(connection); } sdm.addFeature("urn:xmpp:http:upload:0"); // HTTP Upload的特性标识 // 获取HTTP Upload管理器 HttpUploadManager uploadManager = HttpUploadManager.getInstanceFor(connection); File file = new File(path); new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params) { try { // 向服务器请求上传插槽(slot) HttpUploadSlot slot = uploadManager.requestUploadSlot( JidCreate.entityBareFrom("fattaneh123@jabb3r.org"), file.getName(), file.length(), "application/octet-stream" // 根据文件类型调整MIME类型 ); // 使用HTTP PUT将文件上传到指定的URL OkHttpClient client = new OkHttpClient(); RequestBody requestBody = RequestBody.create(file, MediaType.parse("application/octet-stream")); Request request = new Request.Builder() .url(slot.getPutUrl()) .put(requestBody) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { // 上传成功后,通过XMPP消息发送下载URL给对方 Message message = new Message(JidCreate.entityBareFrom("fattaneh123@jabb3r.org")); message.setBody("我发送了一个文件: " + slot.getGetUrl()); // 也可以使用XEP-0065的文件传输提示,或者自定义的消息扩展 connection.sendStanza(message); return "文件上传并发送成功"; } else { return "文件上传失败: " + response.message(); } } catch (Exception e) { e.printStackTrace(); return "发生错误: " + e.getMessage(); } } @Override protected void onPostExecute(String result) { Log.i("file transfer", result); } }.execute(); }
3. 注意事项
- 确保你的项目依赖了OkHttp(或者其他HTTP客户端),因为Smack的
HttpUploadManager只负责获取上传插槽,实际的文件上传需要你自己实现HTTP请求。 - 根据你发送的文件类型调整MIME类型(比如图片用
image/jpeg,文档用application/pdf等),这样接收端能正确识别文件类型。 - 接收端需要支持HTTP Upload协议才能直接从下载URL获取文件,这也是Xabber和Chat Secure能正常接收的原因。
为什么原来的FileTransferManager不行?
传统的FileTransferManager主要用于XEP-0065(SOCKS5 Bytestreams)和XEP-0047(IBB),但很多现代XMPP服务器更倾向于支持HTTP Upload,因为它更高效,不需要额外的端口转发,对移动端更友好。jabb3r.org显然是优先支持HTTP Upload,所以你需要切换到这个协议。
内容的提问来源于stack exchange,提问作者ali mardani
相关产品推荐
相关产品推荐

