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 ...
随机推荐
- Jquery15 插件
学习要点: 1.插件概述 2.验证插件 3.自动完成插件 4.自定义插件 插件(Plugin)也成为 jQuery 扩展(Extension),是一种遵循一定规范的应用程序接口编写出来的程序.目前 j ...
- 再也不学AJAX了!(一)AJAX概述
"再也不学AJAX了"是一个与AJAX主题相关的文章系列,包含以下三个部分的内容: AJAX概述:主要回答"AJAX是什么"这个问题: 使用AJAX:介绍如何通 ...
- Maven项目mybatis Invalid bound statement (not found)解决方法
最近因为工作需要,要学习mybatis框架.在添加好一些依赖之后,通过mybatis进行数据库的crud操作.但是在测试的时候总是报mybatis:Invalid bound statement (n ...
- bellman-ford(可判负权回路+记录路径)
#include<iostream> #include<cstdio> using namespace std; #define MAX 0x3f3f3f3f #define ...
- tomcat监控,自动重启shell脚本
tomcat监控,自动重启shell脚本如下,取名 monitor_tomcat.sh: #!/bin/sh # func:自动监控tomcat脚本并且执行重启操作 # 获取tomcat进程ID(其中 ...
- LeetCode——Coin Change
Question You are given coins of different denominations and a total amount of money amount. Write a ...
- eclipse中把多个项目放在一个文件夹里
1..Package Explorer 可以在这里打开 2.选择Working sets 3.新建java working set 4.把文件夹显示出来 5.可以把项目移动到文件夹里面了,鼠标左键拖就 ...
- JavaScript对象、JSON对象、JSON字符串的区别
一.首先看下什么是JSON JSON:JavaScript Object Natation,JavaScript对象的表现形式,已经发展成一种轻量级的数据交换格式. JavaScript对象的表现形式 ...
- url传递数据类型
php中传递数据,get或post方式为啥用字符串传递,为什么不能直接用数组形式,用的话可以吗
- Canvas绘制不规则图形,实现可拖动,编辑--V1.0第一篇
目前的工作在做在线的标注工具,接触canvas一年了,各种绘制,基本上图像的交互canvas都可以完成,也写了几篇关于canvas的文章,遇到的问题也写博客上了,对于canvas有问题的朋友可以去看看 ...