iOS-AFNetworking3.0上传大量(1000张)图片到服务器
背景:
最近项目要做上传图片功能,图片必须是高清的,所以不让压缩,上传图片是大量的,比如几百张,这个如果是用afn,将图片直接for循环加入到formData里会出现一个问题,临时变量太多,导致内存紧张,最后程序奔溃。之前写过用自动释放池解决它,但是还是效果不大。如果上传的多的话,内存还是受不了。
解决办法一适用于图片少量的如40张图片
我之前写的在这,可以看看自动释放池的方法,如果你上传图片的数量不多的话,可以用这种方法。也很简单的。链接在这里http://www.jianshu.com/p/9e84fe63d5c0
解决办法二适用于图片大量的如1000张图片
思考,为甚内存会占用那么多呢?就是因为图片一口气读到内存中了。如果咱们上传三五张图片,肯定不会出问题。如何把1000张图片分开传呢?所以必须要用到多线程的知识。创建个队列。然后挨个传。注意不要把文件存到队列里,只要先存一个文件名,执行的时候再去读取文件的内容。如果要是将image传给队列,内存还是会爆的。所以存个图片名字。一个字符串肯定没有image占用的内存大吧。上代码吧。我的图片来源于相册,所以我用的图片id。
/**
创建队列然后开始上传图片
@param LocalIdArray 获取相册的图片id数组,如果你是本地的就传递图片名字数组,或者是沙盒的文件名字数组
*/
- (void)uploadOperation:(NSArray *)LocalIdArray
{
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
self.queue = queue;
//这个就是控制同时上传几张图片的,如果是1的话就是串行队列了。我是4,是并行队列。
queue.maxConcurrentOperationCount = 4;
for (int i = 0; i<LocalIdArray.count; i++)
{
//加上自动释放池,及时的释放临时变量,防止内存奔溃
@autoreleasepool {
NSString *imageName = [NSString stringWithFormat:@"up_%d.jpg",i];
WS(weakSelf)
//创建一个任务
NSBlockOperation *uploadOperation = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf uploadTaskWithLocalId:LocalIdArray[i] imageount:LocalIdArray.count imageName:imageName];
}];
//将任务加入到队列中
[queue addOperation:uploadOperation];
}
}
}
/**
开始上传单张图片
@param LocalId 图片的id
@param count 一共上传多少张图片
@param imageName 图片的名称
*/
- (void)uploadTaskWithLocalId:(NSString *)LocalId imageount:(NSInteger)count imageName:(NSString *)imageName
{
//通过图片的id转化为image,如果是图片名字或者是沙盒图片文件名字那更简单了。
CustomAlbumTool *customAlbumTool = [CustomAlbumTool sharedCustomAlbumTool];
PHFetchResult<PHAsset *> *upAssetArr = [PHAsset fetchAssetsWithLocalIdentifiers:@[LocalId] options:nil];
PHAsset *asset = [upAssetArr firstObject];
UIImage *image = [customAlbumTool getImageWithAsset:asset targetSize:PHImageManagerMaximumSize];
//afn上传的参数
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
dic[@"xxx"] = [UserDataCenter xxx];
dic[@"xxx"] = self.xxx;
//因为afn上传是异步执行的所以创建一个信号量。就是为了让一个任务完全的执行完毕后才执行下一个任务。加信号量就是为了把afn异步转化为同步。如果不转化的话。queue.maxConcurrentOperationCount = 1,也没办法做到队列内同步。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
WS(weakSelf)
[SWAYNetWorking uploadWithUrl:uploadModelUrl parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSData *data = UIImageJPEGRepresentation(image, 1.0);
[formData appendPartWithFileData:data name:@"file" fileName:imageName mimeType:@"image/jpeg"];
} withProgress:^(NSProgress *uploadProgress) {
} success:^(id responseObject) {
//图片成功了让信号量加1
dispatch_semaphore_signal(semaphore);
} failure:^(NSError *error) {
//图片传失败了让信号量加1
dispatch_semaphore_signal(semaphore);
}];
//信号量等待。DISPATCH_TIME_FOREVER 永远等到吧。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
监听全部成功刷新ui,可以定义个int型变量,上传成功一张图片加1。如果等于总的图片数量就相当于上传完成了,那么就刷新UI吧。也可以创建个上传成功刷新UI的任务。添加依赖。在任务里执行刷新UI。
/**
创建队列然后开始上传图片
@param LocalIdArray 获取相册的图片id数组,如果你是本地的就传递图片名字数组,或者是沙盒的文件名字数组
*/
- (void)uploadOperation:(NSArray *)LocalIdArray
{
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
self.queue = queue;
//这个就是控制同时上传几张图片的,如果是1的话就是串行队列了。我是4,是并行队列。
queue.maxConcurrentOperationCount = 4;
NSBlockOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ // 回到主线程执行,方便更新 UI 等
}];
}];
for (int i = 0; i<LocalIdArray.count; i++)
{
//加上自动释放池,及时的释放临时变量,防止内存奔溃
@autoreleasepool {
NSString *imageName = [NSString stringWithFormat:@"up_%d.jpg",i];
WS(weakSelf)
//创建一个任务
NSBlockOperation *uploadOperation = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf uploadTaskWithLocalId:LocalIdArray[i] imageount:LocalIdArray.count imageName:imageName];
}];
//添加依赖。
[completionOperation addDependency:uploadOperation];
//将任务加入到队列中
[queue addOperation:uploadOperation];
}
}
//将刷新UI的任务加入队列,当所有的上传任务结束才会调用completionOperation。
[queue addOperation:completionOperation];
}
如果要是你的业务是不能让一张图片传递失败,那么当有一张图没有传成功的话就直接取消所有任务就行了。
[weakSelf.queue cancelAllOperations];
作者:王银博
链接:http://www.jianshu.com/p/5162df747879
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
iOS-AFNetworking3.0上传大量(1000张)图片到服务器的更多相关文章
- 上传base64格式的图片到服务器
上传base64格式的图片到服务器 /**bash64上传图片 * @param $base64 图片的base64数据 * @param $path 保存路径 */ function base64_ ...
- iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片
图片上传时必要将图片进行压缩,不然会上传失败 首先是同系统相册选择图片和视频.iOS系统自带有UIImagePickerController,可以选择或拍摄图片视频,但是最大的问题是只支持单选,由于项 ...
- iOS上架ipa上传问题那些事
iOS上架ipa上传问题那些事 原文: http://www.jianshu.com/p/1e22543285c2 字数513 阅读312 评论0 喜欢1 通过xcode直接打包上传,不会提示你的ip ...
- MVC下form表单一次上传多种类型的图片(每种类型的图片可以上传多张)
form表单一次上传多种类型的图片(每种类型的图片可以上传多张) controller中的action方法 public ActionResult UploadImage( ) { in ...
- iOS多图上传
iOS多图上传涉及到多线程问题,个人比较喜欢使用GCD操作,下边是最近写的一个多图上传代码,附带相关注释 __block BOOL allSucc = YES; __block int m = 0; ...
- 【iOS 使用github上传代码】详解
[iOS 使用github上传代码]详解 一.github创建新工程 二.直接添加文件 三.通过https 和 SSH 操作两种方式上传工程 3.1https 和 SSH 的区别: 3.1.1.前者可 ...
- Servlet3.0上传
1.上传对表单限制 *method=post *Enctype=multipart/form-data,它的默认值是:application/x-www-form-urlencoded 表单中需要添加 ...
- Servlet学习:(三)Servlet3.0 上传文件
转: Servlet学习:(三)Servlet3.0 上传文件 2018年08月03日 11:57:58 iDark_CSDN 阅读数:362 一.注意事项 客户端(浏览器) 表单的提交方法必须是 ...
- iOS - (多图上传已封装)
/*** 上传带图片的内容,允许多张图片上传(URL)POST** @param url 网络请求地址* @param images ...
- iOS 一次上传多张图片, 并返回进度值
我封装的使用AFNetworking上传多图的一个方法.带进度条回调,希望对你用帮助,我app中亲测可用,不知道你的服务器是如何接收数据的: /** * 上传带图片的内容,允许多张图片上传(URL)P ...
随机推荐
- 【前端】用javaScript实现实现一个球池的效果
ballPool 用javaScript实现实现一个球池的效果,实现效果如下所示: 动图: 截图: HTML代码: <!DOCTYPE html> <html > <he ...
- centos下利用mail命令进行邮件发送
centos下默认自带mail命令: 可以用如下命令查看存放位置: which mail 结果如下: 如果没有安装可以使用 如下命令安装 yum -y install mailx 利用mail命令进行 ...
- apache解压版安装服务
解压版也就是绿色版 到apache/bin目录 然后运行下面命令 httpd.exe -k install -n "Apache24" 如果要卸载服务的话,就是下面这个命令 htt ...
- ELK 6.x 部署
Elasticsearch版本:6.3.2 Kibana版本:6.3.2 1.es安装 按照官方提示操作即可. 通过yum安装或者下载tar包解压. 安装完成之后,需要修改一些配置 ①修改文件 /et ...
- MySQL索引底层实现
一.定义 索引定义:索引(Index)是帮助MySQL高效获取数据的数据结构.本质:索引是数据结构. 二.B-Tree m阶B-Tree满足以下条件: 每个节点至多可以拥有m棵子树. 根节点,只有至少 ...
- 可以,得驾证了\(^o^)/
说实在话,我自认为我不太适合开车. 首先我有点晕车,在车上坐久了就头晕脑胀. 心里素质也不行,凡是遇到什么事了,就慌慌张张,手忙脚乱. 然后就是练车一点都不稳,每次练车都会有新问题出现. 先说一下我科 ...
- tags
运行tags在你的.vimrc 中加一个路径,set tags=/home/lh/1407k/arm/tags 注意此文件下的东西要注销必须用“执行一个ctags -R *;ctrl + ]过去,ct ...
- Linux下部署 jar包
1.windows和linux执行jar命令是一样的,java -jar xxx.jar 2.使用nohup命令将jar程序设置成后台运行,运行日志输出到nohup.out,关闭窗口无影响 nohup ...
- python UI自动化测试
为了减小维护成本: 1.UI自动化测试需要有较为稳定的环境 2.代码设计合理,那么我们就需要面向对象的设计一个框架,将重复的代码模块化 一.首先总结一下 UI自动化大概要哪些模块 1.config(配 ...
- HTML DOM(二):节点的增删改查
上一篇讲述了DOM的基本知识,从其得知,在DOM眼中,HTML的每个成分都可以看作是节点(文档节点.元素节点.文本节点.属性节点.注释节点,其中,属性节点是属于元素节点),本篇的内容就是通过DOM对这 ...