总结一下大文件分片上传和断点续传的问题。因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况。http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传。所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这就是分片的基本原理。断点续传要求本地要记录每一片的上传的状态,我通过三个状态进行了标记(wait  loading  finish),当网络中断,再次连接后,从断点处进行上传。服务器通过文件名、总片数判断该文件是否已全部上传完成。

下面来说细节:

1、首先获取文件(音视频、图片)

分两种情况,一种是在相册库里直接获取,一种是调用相机。如果是通过UIImagePickerView来获取(细节不详述,网上一大堆),我们会发现当你选定一个视频的时候,会出现图1的压缩页面,最后我们的app获取的视频就是这个经过压缩后的视频(不是视频库里的原始视频,这里有个注意点,操作完该压缩视频后记得释放,系统不会帮你释放的,需要你手动来操作,下面会说到),然后通过UIImagePickerView的协议方法中的- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info获取视频的Info

fileInfo = {

UIImagePickerControllerMediaType = "public.movie";

UIImagePickerControllerMediaURL = "file:///private/var/mobile/Containers/Data/Application/2AAE9E44-0E6D-4499-9AC3-93D44D8342EA/tmp/trim.F36EC46C-4219-43C8-96A7-FA7141AB64D2.MOV";

UIImagePickerControllerReferenceURL = "assets-library://asset/asset.MOV?id=DEDA9406-3223-4F87-ABB2-98FB5F5EB9C4&ext=MOV";

}

UIImagePickerControllerMediaType是选取文件的类型,如KUTTypeImage,KUTTypeMovie。这里注意一下movie和video的区别,一个是有声音的视频文件,一个是没有声音的视频文件,当然还有Audio是只有声音没有视频。UIImagePickerControllerMediaURL是视频的URL(如果是相机拍摄的,那么这个就是原始拍摄得到的视频;如果是在相册库里选择的,那就是压缩之后生成的视频),注意这个URL不指向相册库,通过这个URL你可以操作这个视频如删除,拷贝等,可以获取压缩后的视频的大小。UIImagePickerControllerReferenceURL是一个指向相册的URL,官方的解释是an NSURL that references an asset in the AssetsLibrary framework,通过这个URL,你可以获取视频的所有信息,包括文件名,缩略图,时长等(通过ALAssetsLibrary里的assetsLibraryassetForURL:referenceURLresultBlock:)。

如果是相机拍摄的,注意两个保存方法:图片保存到相册assetsLibrarywriteImageDataToSavedPhotosAlbum:UIImageJPEGRepresentation([infovalueForKey:UIImagePickerControllerOriginalImage],(CGFloat)1.0)metadata:nilcompletionBlock: failureBlock:

高保真压缩图片的方法NSData * UIImageJPEGRepresentation ( UIImage *image, CGFloat compressionQuality)

视频保存到相册:assetsLibrary writeVideoAtPathToSavedPhotosAlbum:MediaURL completionBlock:failureBlock:

到这里,我们就获取了所有需要的文件以及文件信息。下面要做的就是将文件分片。

2、将获取到的文件分片

首先,我将获取到的文件保存在这这样一个类中

@interface CNFile : NSObject

@property (nonatomic,copy)NSString* fileType;//image  or  movie

@property (nonatomic,copy)NSString* filePath;//文件在app中路径

@property (nonatomic,copy)NSString* fileName;//文件名

@property (nonatomic,assign)NSInteger fileSize;//文件大小

@property (nonatomic,assign) NSInteger trunks;//总片数

@property (nonatomic,copy)NSString* fileInfo;

@property (nonatomic,strong)UIImage* fileImage;//文件缩略图

@property (nonatomic,strong) NSMutableArray* fileArr;//标记每片的上传状态

@end

这样我们就可以对每一个CNFile对象进行操作了。

-(void)readDataWithChunk:(NSInteger)chunk file:(CNFile*)file{

总片数的获取方法:

int offset =1024*1024;(每一片的大小是1M)

NSInteger chunks = (file.fileSize%1024==0)?((int)(file.fileSize/1024*1024)):((int)(file.fileSize/(1024*1024) + 1));

NSLog(@"chunks = %ld",(long)chunks);

将文件分片,读取每一片的数据:

NSData* data;

NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:file.filePath];

[readHandle seekToFileOffset:offset * chunk];

data = [readHandle readDataOfLength:offset];

}

这样我们就获取了每一片要上传的数据,然后询问服务器,该片是否已经存在

(方法-(void)ifHaveData:(NSData*)data WithChunk:(NSInteger)chunk file:(CNFile*)file)

,如果存在,令chunk+1,重复上面的方法读取下一片,直到服务器不存在该片,那么上传该片数据。在这个方法中注意设置该chunk的上传状态(wait  loading finish),这将关系到本地判断该文件是否已全部上传完成。

下一步就是上传的过程:

-(void)uploadData:(NSData*) data WithChunk:(NSInteger) chunk file:(CNFile*)file;

在服务器返回该片上传成功后,我们要做的事有很多:

1)先将已经成功上传的本片的flag置finish

[file.fileArr replaceObjectAtIndex:chunk withObject:@“finish"];

2)查看是否所有片的flag都已经置finish,如果都已经finishi,说明该文件上传完成,那么删除该文件,上传下一个文件或者结束。

for (NSInteger j =0; j<chunks; j++){

if (j == chunks || ((j == chunks -1)&&([file.fileArr[j]isEqualToString:@"finish"])))

[me deleteFile:file.filePath];

[me readNextFile];

}

3)如果没有都finish,那么看本地下一chunk对用的flag是否是wait

NSLog(@"查看第%ld片的状态",chunk+1);

for(NSInteger i = chunk+1;i < chunks;i++)

{

NSString* flag = [file.fileArrobjectAtIndex:i];

if ([flagisEqualToString:@"wait"]) {

[me readDataWithChunk:ifileName:fileNamefile:file];

break;

}

}

在第2、3步之间可以有一个 2.5)判断是否暂停上传

if(me.isPause ==YES)

{

//将目前读到了第几个文件的第几片保存到本地

[self saveProgressWithChunk:chunk file:file];

return ;

}

这个操作实际上和上传过程中断网是一样的,为了断点续传,在断网或者暂停的时候,我们要将目前的进度保存起来,以便下次上传时略过前面已置finish的片。

然后还有一个问题,如果我们就这样线性的一片一片上传,实际上失去了分片上传的意义,应该结合多线程,使分片上传过程并发执行,同时上传多片,这样就提高了上传效率,并充分利用了网络带宽。

dispatch_async(dispatch_queue_t queue, ^{

[me readDataWithChunk: chunk];

})

最后注意一下,每上传完一个视频,去设置里看看你的app占用的存储空间有没有增大哦,如果你没有处理那个生成的压缩视频,你会发现你的app的空间占用量是很大的。

详细参考这篇文章:http://blog.ncmem.com/wordpress/2019/08/12/%e5%a4%a7%e6%96%87%e4%bb%b6%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0-2/

vue+大文件上传控件的更多相关文章

  1. vue大文件上传控件选哪个好?

    需求: 项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在20G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以20G来进行限制. PC端全平台支持,要求支持Window ...

  2. 因用了NeatUpload大文件上传控件而导致Nonfile portion > 4194304 bytes错误的解决方法

    今天遇到一个问题,就是“NeatUpload大文件上传控件而导致Nonfile portion > 4194304 bytes错误”,百度后发现了一个解决方法,跟大家分享下: NeatUploa ...

  3. 绝对好用Flash多文件大文件上传控件

    本实例采用的是Uploadify上传插件,.NET程序,源程序是从网上找的,但是有Bug,已经修改好,并标有部分注释.绝对好用,支持单文件.多文件上传,支持大文件上传,已经过多方面测试,保证好用. 以 ...

  4. 大文件上传控件webupload插件

    之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...

  5. Web大文件上传控件-asp.net-bug修复-Xproer.HttpUploader6.2

    版权所有 2009-2016荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...

  6. Web大文件上传控件-bug修复-Xproer.HttpUploader6

    1.修复上传文件夹时,文件夹大小可能不正确的问题.这个问题是由于以MD5模式上传时没有更新文件夹总大小导致.   更新fd_complete.aspx   更新DBFile.cs-fd_complet ...

  7. web大文件上传控件-监控fd_create流程-Xproer.HttpUploader6

      监控fd_create流程 1.打开ie,f12 2.启动网络监控 点击开始捕获 上传文件夹,然后查看监控 将监控信息转到详细视图

  8. web大文件上传控件-监控f_create流程-Xproer.HttpUploader6

    监控f_create流程 1.打开ie,f12 2.启动网络监控 点击开始捕获 上传文件,然后查看监控 将监控信息转到详细视图 向f_create提交的数据 f_create返回值

  9. web大文件上传控件-设置附加参数-Xproer.HttpUploader6

    自定义附加字段在up6.js中定义,也可以不用定义: 注意: 1.附加字段必须是字符串类型. 2.如果附加字段的值包含中文,在上传前必须使用encodeURIComponent进行编码.     在引 ...

随机推荐

  1. zabbix添加自定义监控(自动发现)遇到的问题

    问题:zabbix添加自动发现端口,提示Value should be a JSON object [root@localhost zabbix_agentd.d]# zabbix_get -s 19 ...

  2. thrift原理与架构

    是什么: 一个RPC框架.

  3. 以前我对你不够好,我也很难受——CSS篇

    1)文字下划线.删除线.定划线 Text-decoration:underline /*下划线*/ Text-decoration:overline     /*顶划线*/ Text-decorati ...

  4. The Art Of Loving

    The Art Of Loving 来源 https://www.zhihu.com/question/23720541 ----------------------------- 茫然的蒲公英 有书 ...

  5. java线程的五种状态

    五种状态 开始状态(new) 就绪状态(runnable) 运行状态(running) 阻塞状态(blocked) 结束状态(dead) 状态变化 1.线程刚创建时,是new状态 2.线程调用了sta ...

  6. 《你不知道的Javascript》感悟篇—对象属性遍历的那些事

    划重点 本篇笔者将重点介绍JavaScript中 getOwnPropertyNames .Object.keys.for ... in 的使用及他们之间的异同点. getOwnPropertyNam ...

  7. iview-admin本地测试上线登陆问题和文件路径找不到问题

    在项目中vue.config.js下修改上线路径(图中我修改为:根目录路径) 测试本地上线登陆出现问题: 在main.js下if (process.env.NODE_ENV !== 'producti ...

  8. ceph集群部署(基于jewel版)

    环境 两个节点:ceph1.ceph2 ceph1: mon.mds.osd.0.osd.1 ceph2: osd.2.osd.3 网络配置: ceph1: 管理网络,eth0,10.0.0.20 存 ...

  9. Linux安全:Linux如何防止木马

    (一)解答战略 去企业面试时是有多位竞争者的,因此要注意答题的维度和高度,一定要直接秒杀竞争者,搞定高薪offer. (二)解答战术 因为Linux下的木马常常是恶意者通过Web的上传目录的方式来上传 ...

  10. 【charlse】charlse功能

    (一)主界面介绍 一.工具导航栏 Charles 顶部为菜单导航栏,菜单导航栏下面为工具导航栏.视图如下图所示: 工具导航栏中提供了几种常用工具:  :清除捕获到的所有请求  :红点状态说明正在捕获请 ...