iOS大文件的分片上傳和斷點上傳

由于最近比較忙芒率,所以一直沒有寫博客,現(xiàn)在分享一些大文件的上傳的問題篙顺!斷點續(xù)傳和分片上傳偶芍。因為文件過大(比如1G以上)充择,必須要考慮上傳過程網(wǎng)絡(luò)中斷的情況。http的網(wǎng)絡(luò)請求中本身就已經(jīng)具備了分片上傳功能匪蟀,當(dāng)傳輸?shù)奈募容^大時椎麦,http協(xié)議自動會將文件切片(分塊),但這不是我們現(xiàn)在說的重點材彪,我們要做的事是保證在網(wǎng)絡(luò)中斷后1G的文件已上傳的那部分在下次網(wǎng)絡(luò)連接時不必再重傳观挎。所以我們本地在上傳的時候,要將大文件進(jìn)行分片段化,比如分成1024*1024B嘁捷,即將大文件分成1M的片進(jìn)行上傳,服務(wù)器在接收后显熏,再將這些片合并成原始文件雄嚣,這就是分片的基本原理。斷點續(xù)傳要求本地要記錄每一片的上傳的狀態(tài)喘蟆,我通過三個狀態(tài)進(jìn)行了標(biāo)記(wait loading finish)缓升,當(dāng)網(wǎng)絡(luò)中斷,再次連接后履肃,從斷點處進(jìn)行上傳仔沿。服務(wù)器通過文件名、總片數(shù)判斷該文件是否已全部上傳完成尺棋。


下面來說細(xì)節(jié):

1封锉、首先獲取文件(音視頻、圖片)

分兩種情況膘螟,一種是在相冊庫里直接獲取成福,一種是調(diào)用相機(jī)。如果是通過UIImagePickerView來獲染2小(細(xì)節(jié)不詳述奴艾,網(wǎng)上一大堆),我們會發(fā)現(xiàn)當(dāng)你選定一個視頻的時候内斯,會出現(xiàn)圖1的壓縮頁面蕴潦,最后我們的app獲取的視頻就是這個經(jīng)過壓縮后的視頻(不是視頻庫里的原始視頻,這里有個注意點俘闯,操作完該壓縮視頻后記得釋放潭苞,系統(tǒng)不會幫你釋放的,需要你手動來操作真朗,下面會說到)此疹,然后通過UIImagePickerView的協(xié)議方法中的- (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的區(qū)別湖笨,一個是有聲音的視頻文件,一個是沒有聲音的視頻文件蹦骑,當(dāng)然還有Audio是只有聲音沒有視頻慈省。UIImagePickerControllerMediaURL是視頻的URL(如果是相機(jī)拍攝的,那么這個就是原始拍攝得到的視頻脊串;如果是在相冊庫里選擇的辫呻,那就是壓縮之后生成的視頻),注意這個URL不指向相冊庫琼锋,通過這個URL你可以操作這個視頻如刪除,拷貝等祟昭,可以獲取壓縮后的視頻的大小缕坎。UIImagePickerControllerReferenceURL是一個指向相冊的URL,官方的解釋是an NSURL that references an asset in the AssetsLibrary framework篡悟,通過這個URL谜叹,你可以獲取視頻的所有信息,包括文件名搬葬,縮略圖荷腊,時長等(通過ALAssetsLibrary里的assetsLibraryassetForURL:referenceURLresultBlock:)。

如果是相機(jī)拍攝的急凰,注意兩個保存方法:圖片保存到相冊assetsLibrarywriteImageDataToSavedPhotosAlbum:UIImageJPEGRepresentation([infovalueForKey:UIImagePickerControllerOriginalImage],(CGFloat)1.0)metadata:nilcompletionBlock: failureBlock:

高保真壓縮圖片的方法NSData * UIImageJPEGRepresentation ( UIImage *image, CGFloat compressionQuality)

視頻保存到相冊:assetsLibrarywriteVideoAtPathToSavedPhotosAlbum: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)NSIntegerfileSize;//文件大小

@property (nonatomic,assign)NSIntegertrunks;//總片數(shù)

@property(nonatomic,copy)NSString* fileInfo;

@property(nonatomic,strong)UIImage* fileImage;//文件縮略圖

@property(nonatomic,strong) NSMutableArray* fileArr;//標(biāo)記每片的上傳狀態(tài)

@end

這樣我們就可以對每一個CNFile對象進(jìn)行操作了床三。

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

總片數(shù)的獲取方法:

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

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

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

將文件分片一罩,讀取每一片的數(shù)據(jù):

NSData* data;

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

[readHandleseekToFileOffset:offset * chunk];

data = [readHandlereadDataOfLength:offset];

}

這樣我們就獲取了每一片要上傳的數(shù)據(jù),然后詢問服務(wù)器撇簿,該片是否已經(jīng)存在

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

聂渊,如果存在,令chunk+1四瘫,重復(fù)上面的方法讀取下一片汉嗽,直到服務(wù)器不存在該片,那么上傳該片數(shù)據(jù)莲组。在這個方法中注意設(shè)置該chunk的上傳狀態(tài)(wait loading finish)诊胞,這將關(guān)系到本地判斷該文件是否已全部上傳完成。

下一步就是上傳的過程:

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

在服務(wù)器返回該片上傳成功后撵孤,我們要做的事有很多:

1)先將已經(jīng)成功上傳的本片的flag置finish

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

2)查看是否所有片的flag都已經(jīng)置finish迈着,如果都已經(jīng)finishi,說明該文件上傳完成邪码,那么刪除該文件裕菠,上傳下一個文件或者結(jié)束。

for(NSIntegerj =0; j

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

[medeleteFile:file.filePath];

[mereadNextFile];

}

3)如果沒有都finish闭专,那么看本地下一chunk對用的flag是否是wait

NSLog(@"查看第%ld片的狀態(tài)",chunk+1);

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

{

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

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

[mereadDataWithChunk:ifileName:fileNamefile:file];

break;

}

}

在第2奴潘、3步之間可以有一個 2.5)判斷是否暫停上傳

if(me.isPause ==YES)

{

//將目前讀到了第幾個文件的第幾片保存到本地

[selfsaveProgressWithChunk:chunk file:file];

return;

}

這個操作實際上和上傳過程中斷網(wǎng)是一樣的,為了斷點續(xù)傳影钉,在斷網(wǎng)或者暫停的時候画髓,我們要將目前的進(jìn)度保存起來,以便下次上傳時略過前面已置finish的片平委。

然后還有一個問題奈虾,如果我們就這樣線性的一片一片上傳,實際上失去了分片上傳的意義廉赔,應(yīng)該結(jié)合多線程肉微,使分片上傳過程并發(fā)執(zhí)行,同時上傳多片蜡塌,這樣就提高了上傳效率碉纳,并充分利用了網(wǎng)絡(luò)帶寬。

dispatch_async(dispatch_queue_t queue, ^{

[mereadDataWithChunk: chunk];

})

最后注意一下馏艾,每上傳完一個視頻劳曹,去設(shè)置里看看你的app占用的存儲空間有沒有增大哦,如果你沒有處理那個生成的壓縮視頻攒至,你會發(fā)現(xiàn)你的app的空間占用量是很大的厚者。


站在大牛的肩膀上開發(fā)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迫吐,一起剝皮案震驚了整個濱河市库菲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌志膀,老刑警劉巖熙宇,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異溉浙,居然都是意外死亡烫止,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門戳稽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馆蠕,“玉大人期升,你說我怎么就攤上這事』ス” “怎么了播赁?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吼渡。 經(jīng)常有香客問我容为,道長,這世上最難降的妖魔是什么寺酪? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任坎背,我火速辦了婚禮,結(jié)果婚禮上寄雀,老公的妹妹穿的比我還像新娘得滤。我一直安慰自己,他們只是感情好盒犹,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布耿戚。 她就那樣靜靜地躺著,像睡著了一般阿趁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坛猪,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天脖阵,我揣著相機(jī)與錄音,去河邊找鬼墅茉。 笑死命黔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的就斤。 我是一名探鬼主播悍募,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洋机!你這毒婦竟也來了坠宴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绷旗,失蹤者是張志新(化名)和其女友劉穎喜鼓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衔肢,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡庄岖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了角骤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隅忿。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出背桐,到底是詐尸還是另有隱情优烧,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布牢撼,位于F島的核電站匙隔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏熏版。R本人自食惡果不足惜纷责,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撼短。 院中可真熱鬧再膳,春花似錦、人聲如沸曲横。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禾嫉。三九已至灾杰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間熙参,已是汗流浹背艳吠。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留孽椰,地道東北人昭娩。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像黍匾,于是被迫代替她去往敵國和親栏渺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容