成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何在OSS上實現大文件的斷點下載和上傳

云計算
OSS對外提供的是RESTful形式的接口,其最重要的特點之一是無狀態性(statelessness),即OSS服務器不會保持除了單次請求之外的,任何與其通信的客戶端的通信狀態。因此對于斷點續傳這樣有狀態功能的實現,關鍵點在于如何在客戶端完成狀態維護 。

OSS(開放存儲服務)是面向海量非結構化數據對象的存儲服務。隨著云計算的普及和飛速增長,越來越多的開發者把他們的應用建筑在了 OSS之上,然而OSS的開發資料還不是很多。我在這里拋磚引玉,通過回答一個經常被問及的問題——如何在OSS上實現大文件的斷點續傳功能——希望有更多的高手來一同分享自己在云存儲上的開發經驗。

OSS對外提供的是RESTful形式的接口,其最重要的特點之一是無狀態性(statelessness),即OSS服務器不會保持除了單次請求之外的,任何與其通信的客戶端的通信狀態。因此對于斷點續傳這樣有狀態功能的實現,關鍵點在于如何在客戶端完成狀態維護 。在以下章節中,我以Python為例,介紹如何實現OSS的斷點下載和斷點上傳。

1. 在OSS上實現大文件的斷點下載:

所謂斷點下載,就是要從文件已經下載的地方開始繼續下載。為了方便理解,我們先來看一個從OSS下載一個文件保存到本地的Python例子。在這個例子[1]中,我們從一個名為 “lingyun”的bucket里面,下載一個叫“example.dat”的文件,并且以相同名字保存在當前目錄。

from oss_api import *

HOST="oss.aliyuncs.com"

BUCKET = "lingyun"

OBJECT = "example.dat"

ACCESS_ID = "*******************"

SECRET_ACCESS_KEY = "*******************"

#下載文件

oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)

res = oss.get_object(BUCKET, OBJECT)

#保存文件

if 200 == res.status:

f = file(OBJECT, 'w')

f.write(res.read())

f.close()

print "Download succeeded."

else:

print "Download failed."

基于上面的代碼,下面的程序顯示了增加斷點續傳功能的文件下載代碼,變化的地方用粗體標注出來了:

from oss_api import *

HOST="oss.aliyuncs.com" #ads

BUCKET = "lingyun"

OBJECT = "example.dat"

BUFFER_SIZE = 10240 # 寫入數據的buffer大小

ACCESS_ID = "*******************"

SECRET_ACCESS_KEY = "*******************"

oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)

# 流式地將數據寫入文件

def flush_data(file, http_res):

while True:

data = res.read(BUFFER_SIZE)

if len(data) != 0:

file.write(data)

else:

break

# 獲取本地文件長度

f = file(OBJECT, 'a')

file_len = f.tell()

# 設置HTTP Header里面的Range參數,跳過已經收到的數據

headers = {}

headers["range"] = "bytes=" + str(file_len) + "-"

res = oss.get_object(BUCKET, OBJECT, headers)

if 206 == res.status: # 返回指定范圍內的數據

flush_data(f, res)

print "Download succeeded."

else: # 下載失敗

print "Download failed."

f.close()

這段代碼和前段代碼相比,有四處發生了變化:

1) 增加了流式寫入本地文件的邏輯。防止下載的數據對象過大,無法一下子讀入本地的內存中。

2) 向OSS發送數據前,獲取本地文件長度。

3) 構造HTTP的Range Header,要求OSS從指定的位置開始下載。

4) 判斷OSS返回的HTTP值,并做出相應的處理:如果OSS返回206,說明下載的是指定位置范圍內的數據;其他狀態碼表明“Range”參數錯誤或者發生異常。

在使用“Range”這個HTTP 參數時,請注意以下三點:

·Range參數中的文件位置是從0開始,最大值是文件長度減1

·如果Range參數填寫錯誤,OSS將忽視這個參數[2]。

·Range參數設置正確的話,OSS將返回HTTP狀態碼206(不是200)以表示返回的是部分數據

通過“Range”參數,還可以實現大文件的并發下載。這個功能作為思考題留給各位讀者,感興趣的讀者可以自己實現一下。OSS官方的SDK里面也提供了一個多線程下載功能的實現,供大家參考。

2. 在OSS上實現大文件的斷點上傳:

相對于斷點下載,斷點上傳的實現顯然要復雜得多。OSS提供的解決辦法可以理解為:在客戶端將大文件切分成若干適合公網傳輸的小數據塊;然后將這些小數據塊分別上傳到OSS上;最后在OSS服務器端將這些小數據塊合并成最終的文件。為了實現這個功能,OSS單獨發布一套上傳API接口——Multipart Upload。這套API接口共有6個:

· Initiate Multipart Upload:初始化一個Multipart Upload事件

·Upload Part:上傳數據塊

· Complete Multipart Upload:完成一個Multipart Upload事件

· Abort Multipart Upload:中止一個Multipart Upload事件

·List Multipart Uploads:列出所有存在的Multipart Upload事件

·List Parts:列出某個Multipart Upload事件下的所有數據塊

這套接口中定義了兩個唯一識別碼(UUID):Upload ID和Part ID,分別用于標識某個Multipart Upload上傳事件和某個數據塊。一個完整的Multipart上傳過程由以下幾步組成:

1) Initiate Multipart Upload: 初始化一個Multipart Upload事件

客戶端通知OSS要上傳一個大文件,OSS返回給客戶端一個唯一標識這次Multipart上傳事件的Upload ID。Python示例代碼如下:

oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)

res = oss.init_multi_upload(BUCKET, OBJECT)

下面是OSS返回的HTTP結果示例:

BUCKET

OBJECT

0004D4184129F5A1A42663160C4C58B1

其中“0004D4184129F5A1A42663160C4C58B1”就是OSS為這次Multipart Upload事件分配的Upload ID。通過這個接口,用戶只是在OSS上注冊了一個Multipart Upload事件,并沒有任何文件被創建或改變。你可以對同一個文件創建多個Multipart Upload事件,在這些Multipart Upload事件沒有完成(Complete)或被中止(Abort)之前,它們都是同時存在的。

2) Upload Part:上傳數據塊

在客戶端將大文件切分成多個適合公網傳輸大小(建議5MB)的數據塊(Part),然后分別上傳到OSS上,并告知OSS這些數據塊屬于某個Upload ID。Python 示例代碼如下:

oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)

res = oss. upload_part (BUCKET, OBJECT, data, upload_id, part_id )

其中,“data”表示要上傳的Part數據內容;“upload_id”為此次上傳事件的ID;“part_id”是該數據塊的索引。Part ID不但唯一標識這一數據塊,還標識了這個數據塊在整個文件內的相對位置。如果你在同一個Upload ID下,使用一個已上傳過的Part ID上傳了新的數據,那么OSS上已有的這個part數據將被覆蓋。除了最后一塊Part數據沒有大小限制以外,其他的Part數據不能小于5MB。Part ID的有效范圍是1~10000。OSS并不要求屬于同一個Upload ID的Part ID必須是連續的,比如:用戶可以只上傳Part ID為1、16、51的數據塊;但Part ID的大小表示了數據塊之間的相對位置,例如Part ID為16的數據塊,在整個文件中必須在Part ID為51的數據塊之前。Upload Part命令執行成功后,OSS會返回這個Part數據的MD5值給客戶端。用戶需要保存這些MD5值,以便在OSS上最后生成文件時使用。

3) Complete Multipart Upload:完成一個Multipart Upload事件

在上傳完所有的數據塊到OSS上之后,我們就可以要求OSS在服務器端將指定的某個Upload ID所屬的數據塊組合成最終的文件。在執行該操作時,客戶端需要提供一個XML格式的文件,其中詳細列舉出了該文件所需的Part ID及其對應的MD5值。一個XML的例子如下:

<CompleteMultipartUpload>

<Part>

<PartNumber>1</PartNumber>

<ETag>1DC6D29FD1E1989793B83F5C2FD0C5E0</ETag>

</Part>

<Part>

<PartNumber>16</PartNumber>

<ETag>E17AC4037030A1227D1C1B115619C6F1</ETag>

</Part>

<Part>

<PartNumber>51</PartNumber>

<ETag>807014FC970ED07BA28DE40B20E5BD59</ETag>

</Part>

</CompleteMultipartUpload>

 

 

 

當我們構建好這個XML文件后,就可以通過調用OSS Python SDK的接口來發送完成Multipart Upload事件的請求,代碼示例如下:

oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)

res = oss.complete_upload(BUCKET, OBJECT, upload_id, part_msg_xml)

OSS收到提交的XML列表后,會逐一判斷每個Part是否存在,以及對應的MD5值是否和客戶端提供的MD5值相等。當所有的Part驗證通過后,OSS將把這些數據Part組合成一個最終的Object。需要注意的是,用戶可以在這次請求里,不指定所有已經上傳的Part。例如,剛才我們成功上傳了1、16和51共三個數據塊到某個Upload ID名下,我們可以只指定用Part 1、51來組成最后的文件(注意Part的ID仍然要求是升序的)。當OSS生成最終的文件后,會將沒有用到的16號Part刪除,以釋放磁盤空間。

整個Multipart Upload流程的Python偽代碼如下所示:

#初始化OSS對象

oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)

# 初始化Multipart Upload事件并獲得Upload ID

upload_id = init_multi_upload(oss, bucket_name, object_name)

# 將本地文件分解成為多個part,并計算出每個part的起始位置和長度

(pos_list, len_list) = split_file_to_part_list(file_name)

# 開啟多個線程來上傳part

thread_pool = []

for index in range(0, thread_sum):

# 在create_thread_worker 里調用OSS API上傳指定的part,上傳結果保存在upload_res

upload_thread = create_thread_worker (oss, file_name, pos_list[index],

len_list[index], upload_res[index])

thread_pool.append(upload_thread)

upload_thread.start()

# 等待所有線程結束

for upload_thread in thread_pool:

upload_thread.join()

# 創建最終合成文件的part列表(XML格式)

part_msg_xml = create_part_xml(upload_res)

# 要求OSS完成本次Multipart Upload事件

res = complete_multipart_upload(oss, bucket, object, upload_id, part_msg_xml)

上面的例子中,使用到了OSS提供的三個接口。其余的三個接口主要提供了對Upload ID和Part ID的查詢和刪除,方便用戶的管理。由于篇幅原因,這三個接口就不在這里做展開說明了,感興趣的朋友可以參考《OSS API文檔》里面的相應章節。

在OSS提供的Multipart Upload方法中,由于各個數據塊之間是相互獨立的,所以在傳輸過程中,如果任何一個數據塊傳輸失敗或者進程被掛起,只需要客戶端記錄下每個數據塊的上傳狀態,下次重啟上傳進程時,繼續上傳那些還未上傳成功的數據塊即可,這樣就實現了斷點上傳功能。另外,通過這個接口,還可以實現大文件的并發上傳、向OSS流式地寫入數據等功能,有興趣的讀者可以自己實現一下。

后記:

希望通過這篇文章,大家可以對如何使用OSS進行大文件的斷點下載和上傳的方法有所了解,也希望更多的朋友能分享更多更好的使用OSS的經驗。

[1]為了便于理解,本文的代碼實例忽略了一些簡單的出錯處理以及極端情況的判斷邏輯。

[2] 如果其他參數都合法,這個請求將符合get object請求的語法,OSS會返回整個object的內容,而不是用戶期望的部分數據。

責任編輯:王程程 來源: 51CTO
相關推薦

2015-08-07 15:35:42

ios短點下載源碼

2024-07-02 10:18:18

2021-01-15 11:40:44

文件Java秒傳

2020-04-02 20:07:17

前端vuenote.js

2022-06-13 14:06:33

大文件上傳前端

2021-04-19 05:41:04

JavaScript大文件下載

2021-06-01 05:15:36

JavaScript 前端大文件并發上傳

2023-09-06 08:33:30

2022-06-15 09:01:45

大文件秒傳分片上傳

2019-10-11 08:00:00

Linux命令最大文件

2017-12-20 15:11:48

iOS緩存文件斷點機制

2009-12-07 09:45:23

PHP上傳大文件設置

2024-06-17 09:02:01

2012-03-27 11:08:23

Java

2014-04-09 10:16:28

Linux文件系統fsck工具

2015-12-16 16:01:13

2022-08-05 08:40:37

架構

2023-03-09 12:04:38

Spring文件校驗

2009-11-16 11:41:19

PHP上傳大文件

2015-03-03 13:15:19

ASP.NET大文件下載實現思路
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品免费 | 日韩电影一区 | 国产激情91久久精品导航 | h片在线看 | 中文字幕国产视频 | 看av电影 | 国产精品久久亚洲 | 亚洲精品一区二区三区在线观看 | 91av在线视频观看 | 97久久精品午夜一区二区 | 欧美二级 | 四虎影院免费在线播放 | 中文区中文字幕免费看 | 日韩欧美三级电影在线观看 | 午夜视频免费在线观看 | 日韩国产三区 | 国产网站久久 | 欧美一区二区三区在线播放 | 亚洲品质自拍视频网站 | 亚洲精品大片 | 欧美一区不卡 | 日韩在线视频一区二区三区 | 欧美一卡二卡在线观看 | 久久亚洲国产 | 黄色一级大片在线免费看产 | 国内精品一区二区 | 国产精品久久久久久久久久尿 | 99精品一区二区三区 | 91社区在线高清 | 九九色综合 | 真人毛片| 在线观看成人 | 精品美女久久久 | 欧美一区二区三区视频 | 日韩毛片免费看 | 欧美日韩久| 日韩av成人在线 | 亚洲成人精品一区 | 国产精品国产a | 国产农村妇女精品一区 | 精品一区二区三区在线观看国产 |