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 ...
随机推荐
- HDFS并行复制Distcp
1)Distcp(分布式拷贝)是用于大规模集群内部和集群之间拷贝的工具. 2)distcp命令是以MR作业(没有R任务)的形式实现的,把文件和目录的列表作为M任务的输入.每一个文件是由一个M任务来拷贝 ...
- git如何生成单个文件的补丁
背景:有时候碰到一个commit包含了好几个文件的修改,但是我只需要其中一个文件的修改内容,那么这时候就需要以下方法来生成这一个文件对应修改内容的补丁 答:git format-patch " ...
- Java 线程池submit和execute
submit方法: public abstract class AbstractExecutorService implements ExecutorService { protected <T ...
- 【转】Python 字符串大小写转换
转载自:python 中字符串大小写转换 一.pyhton字符串的大小写转换, 常用的有以下几种方法: 1.对字符串中所有字符(仅对字母有效)的大小写转换,有两个方法: print 'just to ...
- 远程线程注入shellcode笔记
#include "stdafx.h" #include <windows.h> #include <stdio.h> char shellcode[] = ...
- vc libcurl 模拟上传文件
http://www.cnblogs.com/killbit/p/5393301.html 附上这篇文章,因为当时就已经想到了模拟上传,但是因为时间关系,所以就直接用PHP写了.现在改进一下,用VC+ ...
- 修饰器Decorator
类的修饰 许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为.目前,有一个提案将这项功能,引入了 ECMAScript. @testable class MyTestableCl ...
- Django 2.0 的路由如何实现正则表达式
在django2.0的路由系统中,摒弃了1.x中的url,而改用path.需要导入path. from django.urls import path,re_path 在1.x中,使用url()即可实 ...
- winform版本自动更新
我们在使用软件的时候经常会遇到升级版本,这也是Winform程序的一个功能,今天就大概说下我是怎么实现的吧(代码有点不完美有小BUG,后面再说) 先说下我的思路:首先在打开程序的时候去拿到我之前在网站 ...
- 设计模式--享元模式C++实现
1定义 使用共享对象可有效的支持大量细粒度的对象 2类图 角色分析 Flyweight抽象享元角色,一个产品的抽象,定义内部状态和外部状态的接口或者实现 ConcreteFlyweight具体享元角色 ...