xmpp中发送文件和接收文件的处理有些不太一样,接收文件处理比较简单,发送稍微复杂一些。

首先需要在XMPPFramework.h中添加文件传输类

//文件传输
//接收文件
#import "XMPPIncomingFileTransfer.h"
//发送文件
#import "XMPPOutgoingFileTransfer.h"

1、文件接收

文件的接收是被动的,所以需要在XMPPStream初始化的地方加入文件接收模块:

//5、文件接收
_xmppIncomingFileTransfer = [[XMPPIncomingFileTransfer alloc] initWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)];
[_xmppIncomingFileTransfer activate:self.xmppStream];
[_xmppIncomingFileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
//设置为自动接收文件,当然也可以在代理方法中弹出一个alertView来让用户选择是否接收
[_xmppIncomingFileTransfer setAutoAcceptFileTransfers:YES];

添加文件接收的代理XMPPIncomingFileTransferDelegate,

因为文件的接收XMPP不会为我们生成相应的消息,因此必须实现文件接收的代理方法:

#pragma mark ===== 文件接收=======
/** 是否同意对方发文件给我 */
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender didReceiveSIOffer:(XMPPIQ *)offer
{
NSLog(@"%s",__FUNCTION__);
//弹出一个是否接收的询问框
// [self.xmppIncomingFileTransfer acceptSIOffer:offer];
} - (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender didSucceedWithData:(NSData *)data named:(NSString *)name
{
XMPPJID *jid = [sender.senderJID copy];
NSLog(@"%s",__FUNCTION__);
//在这个方法里面,我们通过带外来传输的文件
//因此我们的消息同步器,不会帮我们自动生成Message,因此我们需要手动存储message
//根据文件后缀名,判断文件我们是否能够处理,如果不能处理则直接显示。
//图片 音频 (.wav,.mp3,.mp4)
NSString *extension = [name pathExtension];
if (![@"wav" isEqualToString:extension]) {
return;
}
//创建一个XMPPMessage对象,message必须要有from
XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:jid];
//<span class="s1" style="font-family: 'Comic Sans MS';">给</span><span class="s2" style="font-family: 'Comic Sans MS';">Message</span><span class="s1" style="font-family: 'Comic Sans MS';">添加</span><span class="s2" style="font-family: 'Comic Sans MS';">from</span>
[message addAttributeWithName:@"from" stringValue:sender.senderJID.bare];
[message addSubject:@"audio"]; //保存data
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:[XMPPStream generateUUID]];
path = [path stringByAppendingPathExtension:@"wav"];
[data writeToFile:path atomically:YES]; [message addBody:path.lastPathComponent]; [self.xmppMessageArchivingCoreDataStorage archiveMessage:message outgoing:NO xmppStream:self.xmppStream];
}

当[self.xmppMessageArchivingCoreDataStorage archiveMessage:message outgoing:NO xmppStream:self.xmppStream];执行完毕会发送通知,然后更新相应的历史消息。

2、文件发送

XMPP发送文件的功能依赖于对方客户端,在XMPPStream建立连接之后会询问对方客户端的特性,然后根据返回的特性,判断对方是否能够接收某一种类型的文件。

而XMPP支持的特性有:

 <query xmlns="http://jabber.org/protocol/disco#info">
* <identity category="client" type="phone"/>
* <feature var="http://jabber.org/protocol/si"/>
* <feature var="http://jabber.org/protocol/si/profile/file-transfer"/>
* <feature var="http://jabber.org/protocol/bytestreams"/>
* <feature var="http://jabber.org/protocol/ibb"/>
* </query>

首先,在聊天控制器中添加一个property,并添加XMPPOutgoingFileTransferDelegate

@property (nonatomic, strong) XMPPOutgoingFileTransfer *xmppOutgoingFileTransfer;

这里录一段音频,然后发送。

添加一个录音按钮,当按钮按下时开始录音startRecord:,按钮抬起时,发送录音sendRecord:,划出按钮区域取消录音cancelRecord:,

- (IBAction)startRecord:(id)sender {
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:[XMPPStream generateUUID]];
path = [path stringByAppendingPathExtension:@"wav"]; NSURL *URL = [NSURL fileURLWithPath:path];
_recorder = [[AVAudioRecorder alloc] initWithURL:URL settings:nil error:nil];
[_recorder prepareToRecord];
[_recorder record];
} - (IBAction)sendRecord:(id)sender {
[_recorder stop];
NSArray *resources = [[JKXMPPTool sharedInstance].xmppRosterMemoryStorage sortedResources:YES];
for (XMPPResourceMemoryStorageObject *object in resources) {
if ([object.jid.bare isEqualToString:self.chatJID.bare]) {
NSData *data = [[[NSData alloc] initWithContentsOfURL:_recorder.url] copy];
NSError *err;
[self.xmppOutgoingFileTransfer sendData:data named:_recorder.url.lastPathComponent toRecipient:object.jid description:nil error:&err];
if (err) {
NSLog(@"%@",err);
}
break;
}
} _recorder = nil;
} - (IBAction)cancelRecord:(id)sender {
[_recorder stop];
[[NSFileManager defaultManager] removeItemAtURL:_recorder.url error:nil];
_recorder = nil;
}

其中发送录音时的,如果发送失败,会在error中返回,失败信息,我这里用Spark做接收客户端,就返回了对方不支持的失败信息。

另外,发送文件也需要自己手动创建并保存一条消息,可以在发送成功的代理方法中创建并保存消息。

- (void)xmppOutgoingFileTransferDidSucceed:(XMPPOutgoingFileTransfer *)sender
{
NSLog(@"xmppOutgoingFileTransferDidSucceed"); XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatJID]; //将这个文件的发送者添加到message的from
[message addAttributeWithName:@"from" stringValue:[JKXMPPTool sharedInstance].xmppStream.myJID.bare];
[message addSubject:@"audio"]; NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:sender.outgoingFileName]; [message addBody:path.lastPathComponent]; [[JKXMPPTool sharedInstance].xmppMessageArchivingCoreDataStorage archiveMessage:message outgoing:NO xmppStream:[JKXMPPTool sharedInstance].xmppStream];
}

Demo地址:https://github.com/Joker-King/ChatDemo

XMPP系列(五)---文件传输的更多相关文章

  1. XMPP——Smack[5]文件传输及离线消息的获取

    三天时间,赶在最后一下午实现了文件的传输,本来需要实现离线文件的发送的,一直没想好怎么弄,找openfire的离线文件插件没找到,后来想出一种方法,起服务器时起了一个系统用户,一直在线,当用户发送离线 ...

  2. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  3. Java开发笔记(一百一十五)使用Socket开展文件传输

    前面介绍了怎样通过Socket在客户端与服务端之间传输文本,当然Socket也支持在客户端与服务端之间传输文件,因为文件本身就是通过I/O流实现读写操作的,所以在套接字的输入输出流中传输文件真是再合适 ...

  4. Netty4.x中文教程系列(五)编解码器Codec

    Netty4.x中文教程系列(五)编解码器Codec 上一篇文章详细解释了ChannelHandler的相关构架设计,版本和设计逻辑变更等等. 这篇文章主要在于讲述Handler里面的Codec,也就 ...

  5. ZT android -- 蓝牙 bluetooth (四)OPP文件传输

    android -- 蓝牙 bluetooth (四)OPP文件传输 分类: Android的原生应用分析 2013-06-22 21:51 2599人阅读 评论(19) 收藏 举报 4.2源码AND ...

  6. ftp (文件传输协议)

    ftp (文件传输协议) 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议” ...

  7. linux下常用文件传输命令 (转)

    因为工作原因,需要经常在不同的服务器见进行文件传输,特别是大文件的传输,因此对linux下不同服务器间数据传输命令和工具进行了研究和总结.主要是rcp,scp,rsync,ftp,sftp,lftp, ...

  8. android asmack 注册 登陆 聊天 多人聊天室 文件传输

    XMPP协议简介 XMPP协议(Extensible Messaging and PresenceProtocol,可扩展消息处理现场协议)是一种基于XML的协议,目的是为了解决及时通信标准而提出来的 ...

  9. 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)

    目录[-] 一.TCP/IP协议 二.TCP与UDP 三.Socket是什么 四.Java中的Socket 五.基本的Client/Server程序 六.多客户端连接服务器 七.信息共享 八.文件传输 ...

随机推荐

  1. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  2. maven跳过单元测试的两个参数区别

    maven在打包过程中需要执行单元测试.但有些时候单元测试已经通过只是想打包时,想跳过测试.maven提供了两个参数跳过测试:maven.test.skip=true 和skipTests. 例子 m ...

  3. 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理

    引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...

  4. java中&和&&的区别 位运算

    1.1. 逻辑与的运算符功能 1.1.1. 测试&& public static void main(String[] args) { int x=5; if (x==6 && ...

  5. TortoiseSVN文件夹图标不显示

    伴随着十二月的脚步,小编带领的市委组织部项目有条不紊的进行着,在最近的项目中遇到一个问题TortoiseSVN文件夹的图标不显示,为什么小编已经安装好TortoiseSVN了,发现文件夹的图标还是系统 ...

  6. unity使用ugui自制调色面板

    突然想实现一个调色面板,然后开工... 首先找找有没有什么接口可调,木有找到,找到一些调用win32实现的本地颜色面板的调用,感觉不科学,反正多平台肯定是搞不定的. 既然没找到,还是老老实实的自己写吧 ...

  7. path和classpath的区别

    path的作用 path是系统用来指定可执行文件的完整路径,即使不在path中设置JDK的路径也可执行JAVA文件,但必须把完整的路径写出来,如C:\Program Files\Java\jdk1.6 ...

  8. 【嵌入式开发】ARM 芯片简介 (ARM芯片类型 | ARM处理器工作模式 | ARM 寄存器 | ARM 寻址)

    : 12MHz 晶振 对应 405 ~ 532 MHz 处理速度; -- : 16K 指令缓存, 16K 数据缓存; -- : 32KB 指令缓存, 32KB 数据缓存; (3) 内存接口对比 : 提 ...

  9. 利用openssl管理证书及SSL编程第1部分: openssl证书管理

    利用openssl管理证书及SSL编程第1部分 参考:1) 利用openssl创建一个简单的CAhttp://www.cppblog.com/flyonok/archive/2010/10/30/13 ...

  10. Java实现二叉树的创建和遍历操作(有更新)

    博主强烈建议跳过分割线前面的部分,直接看下文更新的那些即可. 最近在学习二叉树的相关知识,一开始真的是毫无头绪.本来学的是C++二叉树,但苦于编译器老是出故障,于是就转用Java来实现二叉树的操作.但 ...