php如何实现大文件断点续传-php文件
总结一下大文件分片上传和断点续传的问题。因为文件过大(比如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的空间占用量是很大的。
php如何实现大文件断点续传-php文件的更多相关文章
- iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄
前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传. 在实际开发中,输入输出流用的比较少,但 ...
- php实现大文件断点续传下载实例
php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到. require_once('download.clas ...
- webUploader大文件断点续传学习心得 多文件
二.Jsp代码: <!-- 断点续传 start--> <!-- 隐藏域 实时保存上传进度 --> <input id="jindutiao" t ...
- php解决大文件断点续传
核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...
- web之大文件断点续传
之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...
- vue+大文件断点续传
根据部门的业务需求,需要在网络状态不良的情况下上传很大的文件(1G+).其中会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长,请求超时:3,传输中断,必须重新上传导致前功尽弃.解 ...
- java+大文件断点续传
用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 (本文提供全部源码下载,请访问 https://github.com/1269085759/up6-jsp-mysq ...
- Flash大文件断点续传解决方案
核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...
- HTML5 大文件断点续传完整思路整理
需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...
随机推荐
- netcore 实现一个简单的Grpc 服务端和客户端
参考资料,和详细背景不做赘述. 首先定义prop 文件 syntax ="proto3"; package RouteGrpc; service HelloWorld{ rpc S ...
- 在kali2.0中使用msf图形界面可能会遇到的问题
kali版本:Linux kali 4.9.0-kali3-amd64 #1 SMP Debian 4.9.18-1kali1 (2017-04-04) x86_64 GNU/Linux 编写日期:2 ...
- CentOS Linux修改默认Bash shell为Zsh shell
Shell是在程序员与服务器间建立一个桥梁,它对外提供一系列命令,让我们得以控制服务器.常用的Bash就是Shell的一种,也是Linux下默认Shell程序.这里介绍一种更强大的.更人性化的Shel ...
- Spring Cloud 使用Feign调用服务传递Header中的参数
1.使用Feign 调用其他微服务,尤其是在多级调用的同时,需要将一些共同的参数传递至下一个服务,如:token.比较方便的做法是放在请求头中,在Feign调用的同时自动将参数放到restTempla ...
- 洛谷 P1508 Likecloud 题解
题面 很简单的一个二维DP f[i][j]表示最后吃到(i,j)所能获得的最大值, 那么f[i][j]=max(f[i+1][j-1],f[i+1][j],f[i+1][j+1])+a[i][j]; ...
- js中this.index使用
上面圈出的那句没有执行,因为this.index 是undefined,(也不能直接使用i取代this.index,原因是i不是变化的值,使用alert打印输出的i值始终为3) 解决方式:在for语句 ...
- Jade学习(六)之使用html2jade反编译
我们可以使用html2jade将html编译成jade 首先安装html2jade npm install html2jade -g 用法一:使用html2jade将html转为jade html2j ...
- 084、Prometheus 到底NB在哪里?(2019-05-06 周一)
参考https://www.cnblogs.com/CloudMan6/p/7709970.html 本节学习Prometheus的核心,多维数据模型 比如要监控容器 webapp1 的内存使 ...
- LVS负载均衡常用的工作模式有NAT、DR、和TUN三种,其中DR模式性能最为优越,使用最为广泛。
一.安装LVS LVS的编译安装参考本站文章:http://www.linuxe.cn/post-192.html,对于LVS这种功能性软件,在生产中用yum安装也是没有问题的. 1 yum inst ...
- [PyQt5]动态显示matplotlib作图(一)
完整实例 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QVBoxLayout, QSizePoli ...