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來源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
时间: 2024-12-14 22:41:14

iOS-AFNetworking3.0上传大量(1000张)图片到服务器的相关文章

iOS 使用AFN 进行单图和多图上传 摄像头/相册获取图片,压缩图片

图片上传时必要将图片进行压缩,不然会上传失败 首先是同系统相册选择图片和视频.iOS系统自带有UIImagePickerController,可以选择或拍摄图片视频,但是最大的问题是只支持单选,由于项目要求需要支持多选,只能自己自定义.获取系统图库的框架有两个,一个是ALAssetsLibrary,兼容iOS低版本,但是在iOS9中是不建议使用的:另一个是PHAsset,但最低要求iOS8以上.兼容到iOS7,可以选择了ALAssetsLibrary 现在我们先说选择一张图的情况 一.单图多图上

iOS上架ipa上传问题那些事

iOS上架ipa上传问题那些事 原文: http://www.jianshu.com/p/1e22543285c2 字数513 阅读312 评论0 喜欢1 通过xcode直接打包上传,不会提示你的ipa文件有没有错误,只会提示上传成功与否,但在iTunesStore里构建版本的时候并不能看到上传的ipa版本,因为xcode上传并不会检测ipa文件的可用性.解决办法:使用Application Loader(以下简称AppLoader)上传. 注意: 1.iOS9版本的ipa即使用Xcode7生成

【iOS】文件上传小记

iOS中用系统提供的API能实现能实现文件的上传与下载,分别有两种方式.NSURLConnection与NSURLSession. 其中NSURLConnection是使用很久的的一种方式,NSURLSession是新出来的一种方式. 一. POST方式上传 POST方式提交信息默认使用的是 : *Content-Type:  application/x-www-form-urlencoded. *输入中文时,post方式自动进行转义(苹果中自动). 国内的绝大多数网站都采用这种方式上传文件(支

iOS - (多图上传已封装)

  我封装的使用AFNetworking上传多图的一个方法.带进度条回调,希望对你用帮助,我app中亲测可用,不知道你的服务器是如何接收数据的:声明:/***  上传带图片的内容,允许多张图片上传(URL)POST**  @param url                 网络请求地址*  @param images              要上传的图片数组(注意数组内容需是图片)*  @param parameter           图片数组对应的参数*  @param paramet

IIS7.0上传在大小限制

修改 IIS7的上传文件大小限制的方法: 1.打开IIS管理器,并定位于想要修改限制的网站 2.双击右侧窗口中的asp图标 3.展开最下面那个"限制属性",将最下面的"最大请求实体主体限制"右边属性框内修改成你想要的值(注意:单位为"字节"),如1g则修改为1073741824 4.点击窗口右上角的应用,关闭IIS管理器,如此而已 经过与IIS7的接触发现iis7的确比IIS6更人性化了,其它方面不说,微软在这方面做的还不错.修改好之后,点击右上

【Servlet】利用Servlet3.0标准与JSTL表达式实现文件上传系统,支持图片上传后显示

伴随着JDK1.6一起出现的Servlet3.0标准,使得JSP的文件上传系统不再艰难,此前在JSP的文件上传系统需要<[Jsp]使用jspsmartupload完成简单的文件上传系统>(点击打开链接)类似这样的插件才能完成的文件上传系统,还不支持中文,使得各位程序猿掏空心思才能解决这个问题.现在Servlet3.0对文件上传的方法进行封装,无须分块就可以实现.而且Servlet3.0还不用类似<[Servlet]最简单的Servlet JavaWeb程序>(点击打开链接)在web

iOS之第一次上传app

第一次上传app哦,记录一下,以便下次需要查看. 登录开发者账号 https://developer.apple.com/ 选择Member Center 登录 登录完成后 选择Certificates, Identifiers & Profiles 先生成证书,点击Identifiers 点击添加按钮 取个名字(工程名即可) Bundle ID这个是自己程序的Bundle ID即可 通常默认会选图上这几个.需要用那个就点那个= = 完事确认一下,就submit就好了. ============

从web编辑器 UEditor 中单独提取图片上传,包含多图片单图片上传以及在线涂鸦功能

UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.(抄的...) UEditor是非常好用的富文本web编辑器,而且全中文API和注释,方便学习和使用.特别是图片上传查看及涂鸦功能极为喜欢,但是有很多情况我们并不需要Web编辑器,而只需要图片上传.那么问题来了,提取图片上传哪家强..... 网上有很多图片上传的控件.插件.但都不是那么的完美,有的只有一张图片上传不包含批量上传,有的没有图片查看

【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端

原文地址:http://docode.top/Article/Detail/10002 目录: 1.Http协议上传文件(以图片为例)请求报文体内容格式 2.完整版HttpWebRequest模拟上传文件请求报文内容封装 3.asp.net(c#)使用HttpWebRequest携带请求参数模拟上传文件封装源码下载 一.Http协议上传文件(以图片为例)请求报文体内容格式 首先,我们来看下通过浏览器上传文件的请求报文内容格式,这里以本人自己写的实例为例,如下图.除了能上传图片(即:头像字段),还

上传文件点击后显示图片

HTML代码 <include file="./Application/Home/View/default/Public/homeheader.html" /> <html> <body> <!--<form action="{:U('home/statistics/uploadinformation')}" method="post" enctype="multipart/form-da