1. 程式人生 > >iOS大檔案分片上傳和斷點續傳

iOS大檔案分片上傳和斷點續傳

總結一下大檔案分片上傳和斷點續傳的問題。因為檔案過大(比如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)先將已經成功上傳的本片的flagfinish

[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的空間佔用量是很大的。

如果您有任何指正或疑惑,請聯絡我V  us3211228,若對您有所幫助,請點贊!

相關推薦

java使用WebUploader做檔案的分塊斷點

前言: WebUploader是由Baidu WebFE(FEX)團隊開發的一個簡單的以HTML5為主,FLASH為輔的現代檔案上傳元件。在現代的瀏覽器裡面能充分發揮html5的優勢,同時又不摒棄主流IE瀏覽器,沿用原來的FLASH執行時,相容IE6+,iOS 6+, 

iOS檔案分片斷點

總結一下大檔案分片上傳和斷點續傳的問題。因為檔案過大(比如1G以上),必須要考慮上傳過程網路中斷的情況。http的網路請求中本身就已經具備了分片上傳功能,當傳輸的檔案比較大時,http協議自動會將檔案切片(分塊),但這不是我們現在說的重點,我們要做的事是保證在網路中斷後1G

超大檔案斷點的實現

隨著視訊網站和大資料應用的普及,特別是高清視訊和4K視訊應用的到來,超大檔案上傳已經成為了日常的基礎應用需求。但是在很多情況下,平臺運營方並沒有大檔案上傳和斷點續傳的開發經驗,往往在網上找一些簡單的PHP或者Java程式來實現基本的上傳功能,然而在實際使用中就會發現,這些基於

網頁內實現檔案分片斷點

最近做公司的專案,需要在後臺控制系統中新增一個功能-------向伺服器傳送程式更新包;這些程式更新包大小不固定,但基本都在1G到4G之間,剛開始還真是難倒我了,因為之前的專案中沒有上傳過這麼大的檔案,還要斷點續傳,後來經過查資料,寫DEMO,這個問題終於解決了; 解決辦法: 使用XMLHt

Android 檔案分片斷點任務管理實現

Transer 是一個傳輸框架,目前支援: - 支援 HTTP/HTTPS 斷點續傳下載 - 支援 HTTP/HTTPS 大檔案分片上傳 - 支援 類EventBus的task狀態變更通知,支援三種執行緒的訂閱模式 - 支援 任務分組,分使用者

檔案第二彈(分片、秒斷點)

關鍵部分 前端用file.slice()分塊 前端用FileReader獲取每一分塊的md5值 後端用MultipartFile接受分塊檔案 後端用FileOutputStream拼裝分塊檔案 話不多說,直接上程式碼,我想這是你們最喜歡的

在瀏覽器進行檔案分片(java服務端實現)

最近在做web網盤的系統,網盤最基本的功能便是檔案上傳,但是檔案上傳當遇到大檔案的時候,在web端按傳統方式上傳簡直是災難,所以大檔案上傳可以採用分片上傳的辦法。其主要思路是:1.大檔案上傳時進行分片;2.分片上傳;3.對分片檔案進行合併。 思路比較清晰簡單,但一些問題在於:1.大檔案如何進

檔案分塊第二彈(秒斷點)

關鍵部分 前端用file.slice()分塊 前端用FileReader獲取每一分塊的md5值 後端用MultipartFile接受分塊檔案 後端用FileOutputStream拼裝分塊檔案 話不多說,直接上程式碼,我想這是你們最喜歡的 html &l

PHP檔案分片的實現方法

一、前言 在網站開發中,經常會有上傳檔案的需求,有的檔案size太大直接上傳,經常會導致上傳過程中耗時太久,大量佔用頻寬資源,因此有了分片上傳。 分片上傳主要是前端將一個較大的檔案分成等分的幾片,標識當前分片是第幾片和總共幾片,待所有的分片均上傳成功的時候,在後臺進行合成檔案即可。 二、

springboot 整合 gridfs 、webUploader實現檔案分塊斷點、秒

主要的pom.xml: <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId>

java springboot 檔案分片處理

這裡只寫後端的程式碼,基本的思想就是,前端將檔案分片,然後每次訪問上傳介面的時候,向後端傳入引數:當前為第幾塊問價,和分片總數 下面直接貼程式碼吧,一些難懂的我大部分都加上註釋了: 上傳檔案實體類: /** * 檔案傳輸物件 * @ApiModel和@ApiModelProperty及C

eggJS檔案分片與合併

前臺上傳使用vue+axios 前臺程式碼: // 計算分片總數 for (let i = 0; i < Math.ceil(this.file.size / this.uploadFragment.fragment); i++) { this.uploadFra

檔案分塊以及斷點

var fileMd5; //檔案唯一標識 /******************下面的引數是自定義的*************************/ var fileName;//檔名稱 var oldJindu;//如果該檔案之前上傳過 已經上傳的進度

php檔案分片

HTML <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="widt

檔案那些事兒:多圖檔案斷點功能實現與分析

簡介 看了不少的教程,在系統整合搭建的過程中一般寫到檔案上傳這一節時,基本上實現一個檔案上傳功能就不再繼續拓展,而是就此截止轉而去講解其他的內容了,因為企業級應用開發中這些功能肯定會使用到,企業網站的檔案上傳不可能只有一個單圖上傳,也不可能不實現大檔案的功能處

前段WebUploader;JavaEE檔案分片接收

Web大檔案分片上傳 Web環境中大檔案上傳不能再用form表單一次上傳了,這樣效率太低; 我在不斷嘗試SpringMVC環境下分片接受檔案,最終失敗;原因目測是 SpringMVC、Struts框架是不支援HTML5方式上傳的(這類框架只能支援Form表單

java http檔案斷點專案研究,Github原始碼

1,專案調研 因為需要研究下斷點上傳的問題。找了很久終於找到一個比較好的專案。 在GoogleCode上面,程式碼弄下來超級不方便,還是配置hosts才好,把程式碼重新上傳到了github上面。 效果: 上傳中,顯示進度,時間,百分比。 點選【Pause】暫停,點選

js實現檔案分片的方法

<input type="file" name="file" id="file"> <button id="upload" onClick="upload()">upload</button>var bytesPerPiece = 1024

webuploader在springMVC+jquery+Java開發環境下的檔案分片

參考的文章http://blog.csdn.net/new_sara/article/details/51604997 因為從網上看到的總是和自己專案開發有些許差別,所以也是在除錯了很久之後,發現適合自己專案的程式碼,現在把過程記錄下來,以便以後查閱. 注意: 1,web

Node + js實現檔案分片基本原理及實踐(一)

閱讀目錄 一:什麼是分片上傳? 二:理解Blob物件中的slice方法對檔案進行分割及其他知識點 三. 使用 spark-md5 生成 md5檔案 四. 使用koa+js實現大檔案分片上傳實踐 回到頂部 一:什麼是分片上傳? 分片上傳是把一個大的檔案分成若干塊,一塊一塊的傳輸。這