ASP.NETは、アップロードとダウンロードの大きなファイルを実現します

大容量のファイルの断片化の問題を要約し、壊れたアップロードを再開します。ファイルが大きすぎる(例えば、1Gなど以上)であるので、あなたは、ネットワーク障害のアップロードプロセスのケースを考慮する必要があります。ファイル転送が比較的大きい場合、既にフラグメントのアップロード機能を持っている自身のネットワークhttpリクエストは、HTTPプロトコルが自動的にファイルセクション(ブロック)を移動させ、これは我々が焦点について話しているものではありません、私たちは何をする必要があります1Gは、ネットワークの停止後のファイルの一部が次回にネットワーク接続を再送信することなく、アップロードされたことを確認してください。私たちは地元のアップロード時に大きなファイルが断片化することによって、例えば、1024×1024Bに分割され、1Mのアップロードが、サーバが受信断片にについて、大きなファイルがあり、その後、断片化され、元のファイルの中にこれらの作品を結合します基本原理。再び接続されたネットワーク障害が、ブレークポイントからアップロードするときHTTPは、各ピースの状態を記録するローカルアップロードを必要とし、Iは、三つの状態を介して(ローディング完了を待つ)タグ付けされました。ファイルには、すべてのアップロードが完了したかどうかを判断するために、ファイル名、錠剤の合計数によってサーバー。

        以下は詳細です。

  1、最初のファイル(オーディオやビデオ、写真)を取得

2つのケースは、1は、1つのカメラを呼び出している、アルバムライブラリに直接です。それはUIImagePickerViewで(詳細は、詳細にインターネットをたくさん記載されていない)を取得している場合は、我々はあなたがビデオを選択すると、図1の圧縮されたページがあるだろうことがわかります、そして最終的に我々はアプリが圧縮後に、このビデオで取得しますビデオUIImagePickerViewで、その後、(オリジナルのビデオのないビデオライブラリは、あなたが圧縮されたビデオのリリースの動作を覚えた後、システムは、あなたが、私たちは以下について説明します手動で操作する必要がある、あなたがリリースする助けにはなりません、その時点のノートがあります)プロトコルの方法 - (無効)imagePickerController:(UIImagePickerController *)ピッカーdidFinishPickingMediaWithInfo:(NSDictionaryの*)情報、映像情報を取得

fileInfo = {

    UIImagePickerControllerMediaType = "public.movi​​e"。

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

    UIImagePickerControllerReferenceURL = "?資産ライブラリ://asset/asset.MOV ID = DEDA9406-3223-4F87-ABB2-98FB5F5EB9C4&EXT = MOV";

}

UIImagePickerControllerMediaTypeは、KUTTypeImage、KUTTypeMovieなどのファイルタイプを、選択されています。ここでは、ムービーとビデオの違いに注意して、ビデオファイルの音があり、ビデオファイルはもちろん、音声のみの音には、ビデオではありません、何の音ではありません。UIImagePickerControllerMediaURLは、(カメラが、これはビデオによってキャプチャ元である場合、それはアルバムライブラリ、後に生成されたビデオ圧縮に選択されている場合)ビデオのURLであるURLは、このURLを介して、アルバムライブラリを指していないことに注意してください。あなたは、圧縮されたビデオのサイズを取得することができ、など、コピー、削除などの映像を操作することができます。UIImagePickerControllerReferenceURLは、アルバムのURLへのポインタで、公式の説明はこのURLを通じて、AssetsLibraryの枠組みの中で資産を参照するNSURLすべての情報は、あなたがassetsLibraryassetForURL中(ALAssetsLibrary等により、ファイル名、サムネイル、期間、などの映像を、得ることができるということです: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/

おすすめ

転載: www.cnblogs.com/songsu/p/11525529.html