Tải lên tiếp nối

Bạn có thể tải video lên một cách đáng tin cậy hơn bằng cách sử dụng giao thức tải lên tiếp nối cho các API của Google. Giao thức này cho phép bạn tiếp tục hoạt động tải lên sau khi bị gián đoạn mạng hoặc lỗi truyền dẫn khác, giúp tiết kiệm thời gian và băng thông trong trường hợp mạng bị lỗi.

Việc sử dụng tính năng tải lên tiếp nối đặc biệt hữu ích trong các trường hợp sau:

  • Bạn đang chuyển các tệp có dung lượng lớn.
  • Có nhiều khả năng bị gián đoạn mạng.
  • Tệp tải lên bắt nguồn từ một thiết bị có băng thông thấp hoặc kết nối Internet không ổn định, chẳng hạn như thiết bị di động.

Hướng dẫn này giải thích trình tự các yêu cầu HTTP mà ứng dụng thực hiện để tải video lên bằng quy trình tải lên có thể tiếp tục. Hướng dẫn này chủ yếu dành cho những nhà phát triển không thể sử dụng thư viện ứng dụng API của Google, một số thư viện trong đó cung cấp tính năng hỗ trợ gốc cho tính năng tải lên có thể tiếp tục. Trên thực tế, hướng dẫn API Dữ liệu của YouTube – Tải video lên giải thích cách sử dụng Thư viện ứng dụng API của Google cho Python để tải video lên bằng quy trình tải lên có thể tiếp tục.

Lưu ý: Bạn cũng có thể xem loạt yêu cầu được thực hiện để tải lên tiếp tục hoặc bất kỳ thao tác API nào khác bằng cách sử dụng một trong các thư viện ứng dụng API của Google đã bật tính năng ghi nhật ký HTTPS. Ví dụ: để bật dấu vết HTTP cho Python, hãy sử dụng thư viện httplib2:

httplib2.debuglevel = 4

Bước 1 – Bắt đầu một phiên có thể tiếp tục

Để bắt đầu tải video lên có thể tiếp tục, hãy gửi yêu cầu POST đến URL sau. Trong URL, hãy đặt giá trị tham số part thành giá trị thích hợp cho yêu cầu của bạn. Hãy nhớ rằng giá trị tham số xác định các phần chứa thuộc tính mà bạn đang đặt, đồng thời xác định các phần mà bạn muốn phản hồi API bao gồm. Giá trị tham số trong URL yêu cầu phải được mã hoá URL.

https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=PARTS

Đặt nội dung của yêu cầu thành tài nguyên video. Ngoài ra, hãy đặt các tiêu đề yêu cầu HTTP sau:

  • Authorization – Mã thông báo uỷ quyền cho yêu cầu.
  • Content-Length – Số byte được cung cấp trong nội dung của yêu cầu. Xin lưu ý rằng bạn không cần cung cấp tiêu đề này nếu đang sử dụng mã hoá chuyển dữ liệu chia nhỏ.
  • Content-Type – Đặt giá trị thành application/json; charset=UTF-8.
  • X-Upload-Content-Length – Số byte sẽ được tải lên trong các yêu cầu tiếp theo. Đặt giá trị này thành kích thước của tệp mà bạn đang tải lên.
  • x-upload-content-type – loại MIME của tệp mà bạn đang tải lên. Bạn có thể tải tệp lên bằng bất kỳ loại MIME video nào (video/*) hoặc loại MIME là application/octet-stream.

ví dụ sau đây cho thấy cách bắt đầu một phiên có thể tiếp tục để tải video lên. yêu cầu này sẽ đặt (và truy xuất) các thuộc tính trong phần snippetstatus của tài nguyên video, đồng thời truy xuất các thuộc tính trong phần contentdetails của tài nguyên.

post /upload/youtube/v3/videos?uploadType=resumable&part=parts http/1.1
host: www.googleapis.com
authorization: bearer auth_token
content-length: content_length
content-type: application/json; charset=utf-8
x-upload-content-length: x_upload_content_length
X-Upload-Content-Type: X_UPLOAD_CONTENT_TYPE

video resource

Ví dụ sau đây cho thấy một yêu cầu POST đã điền sẵn tất cả các giá trị này, ngoại trừ mã xác thực. Giá trị categoryId trong ví dụ tương ứng với một danh mục video. Bạn có thể truy xuất danh sách các danh mục được hỗ trợ bằng cách sử dụng phương thức videoCategories.list của API.

POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer AUTH_TOKEN
Content-Length: 278
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Length: 3000000
X-Upload-Content-Type: video/*

{
  "snippet": {
    "title": "My video title",
    "description": "This is a description of my video",
    "tags": ["cool", "video", "more keywords"],
    "categoryId": 22
  },
  "status": {
    "privacyStatus": "public",
    "embeddable": True,
    "license": "youtube"
  }
}

Bước 2 – Lưu URI phiên có thể tiếp tục

Nếu yêu cầu của bạn thành công, máy chủ API sẽ phản hồi bằng mã trạng thái HTTP 200 (OK) và phản hồi sẽ bao gồm tiêu đề HTTP Location chỉ định URI cho phiên có thể tiếp tục. Đây là URI mà bạn sẽ dùng để tải tệp video lên.

Ví dụ bên dưới cho thấy phản hồi API mẫu cho yêu cầu ở bước 1:

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
Content-Length: 0

Bước 3 – Tải tệp video lên

Sau khi trích xuất URI phiên từ phản hồi API, bạn cần tải nội dung tệp video thực tế lên vị trí đó. Nội dung của yêu cầu là nội dung tệp nhị phân của video mà bạn đang tải lên. Ví dụ bên dưới cho thấy định dạng của yêu cầu.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: CONTENT_LENGTH
Content-Type: CONTENT_TYPE

BINARY_FILE_DATA

Yêu cầu này đặt các tiêu đề yêu cầu HTTP sau:

  • Authorization – Mã thông báo uỷ quyền cho yêu cầu.
  • Content-Length – Kích thước của tệp bạn đang tải lên. Giá trị này phải giống với giá trị của tiêu đề yêu cầu HTTP X-Upload-Content-Length ở bước 1.
  • Content-Type – Loại MIME của tệp mà bạn đang tải lên. Giá trị này phải giống với giá trị của tiêu đề yêu cầu HTTP X-Upload-Content-Type ở bước 1.

Bước 4 – Hoàn tất quy trình tải lên

Yêu cầu của bạn sẽ dẫn đến một trong các trường hợp sau:

  • Bạn đã tải lên thành công.

    Máy chủ API phản hồi bằng mã phản hồi HTTP 201 (Created). Nội dung của phản hồi là tài nguyên video mà bạn đã tạo.

  • Tài liệu của bạn chưa tải lên thành công nhưng có thể tiếp tục tải lên.

    Bạn có thể tiếp tục tải lên trong một trong các trường hợp sau:

    • Yêu cầu của bạn bị gián đoạn do mất kết nối giữa ứng dụng và máy chủ API. Trong trường hợp này, bạn sẽ không nhận được phản hồi API.

    • Phản hồi API chỉ định bất kỳ mã phản hồi 5xx nào sau đây. Mã của bạn nên sử dụng chiến lược thời gian đợi luỹ thừa khi tiếp tục tải lên sau khi nhận được bất kỳ mã phản hồi nào trong số này.

      • 500Internal Server Error
      • 502Bad Gateway
      • 503Service Unavailable
      • 504Gateway Timeout

    Để tiếp tục tải lên, hãy làm theo hướng dẫn kiểm tra trạng thái tải lêntiếp tục tải lên bên dưới. Hãy nhớ rằng mỗi URI phiên có thể tiếp tục đều có thời lượng tồn tại nhất định và sẽ hết hạn. Do đó, bạn nên bắt đầu quá trình tải lên có thể tiếp nối ngay khi nhận được URI phiên và tiếp tục quá trình tải lên bị gián đoạn ngay sau khi xảy ra tình trạng gián đoạn.

  • Tệp tải lên của bạn không tải lên được vĩnh viễn.

    Đối với trường hợp tải lên không thành công, phản hồi sẽ chứa phản hồi lỗi giúp giải thích nguyên nhân của lỗi. Đối với một lượt tải lên không thành công vĩnh viễn, phản hồi API sẽ có mã phản hồi 4xx hoặc mã phản hồi 5xx khác với các mã nêu trên.

    Nếu bạn gửi yêu cầu kèm theo URI phiên đã hết hạn, máy chủ sẽ trả về mã phản hồi HTTP 404 (Not Found). Trong trường hợp này, bạn cần bắt đầu một quá trình tải lên có thể tiếp nối, lấy URI phiên mới và bắt đầu tải lên từ đầu bằng cách sử dụng URI mới.

Bước 4.1: Kiểm tra trạng thái của tệp tải lên

Để kiểm tra trạng thái của một quá trình tải lên tiếp nối bị gián đoạn, hãy gửi một yêu cầu PUT trống đến URL tải lên mà bạn đã truy xuất ở bước 2 và cũng sử dụng ở bước 3. Trong yêu cầu của bạn, hãy đặt giá trị tiêu đề Content-Range thành bytes */CONTENT_LENGTH, trong đó CONTENT_LENGTH là kích thước của tệp bạn đang tải lên.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 0
Content-Range: bytes */CONTENT_LENGTH

Bước 4.2: Xử lý phản hồi API

Nếu quá trình tải lên đã hoàn tất, bất kể quá trình tải lên đó có thành công hay không, API sẽ trả về cùng một phản hồi mà API đã gửi khi quá trình tải lên ban đầu hoàn tất.

Tuy nhiên, nếu quá trình tải lên bị gián đoạn hoặc vẫn đang diễn ra, thì phản hồi API sẽ có mã phản hồi HTTP 308 (Resume Incomplete). Trong phản hồi, tiêu đề Range chỉ định số byte của tệp đã được tải lên thành công.

  • Giá trị tiêu đề được lập chỉ mục từ 0. Do đó, giá trị tiêu đề là 0-999999 cho biết 1,000,000 byte đầu tiên của tệp đã được tải lên.
  • Nếu bạn chưa tải nội dung nào lên, thì phản hồi API sẽ không bao gồm tiêu đề Range.

Phản hồi mẫu bên dưới cho thấy định dạng của phản hồi API cho một lượt tải lên có thể tiếp tục:

308 Resume Incomplete
Content-Length: 0
Range: bytes=0-999999

Nếu phản hồi API cũng bao gồm tiêu đề Retry-After, hãy sử dụng giá trị của tiêu đề đó để xác định thời điểm tiếp tục tải lên.

Bước 4.3: Tiếp tục tải lên

Để tiếp tục tải lên, hãy gửi một yêu cầu PUT khác đến URL tải lên được ghi lại ở bước 2. Đặt phần nội dung yêu cầu thành mã nhị phân cho phần tệp video chưa được tải lên.

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: REMAINING_CONTENT_LENGTH
Content-Range: bytes FIRST_BYTE-LAST_BYTE/TOTAL_CONTENT_LENGTH

PARTIAL_BINARY_FILE_DATA

Bạn cần đặt các tiêu đề yêu cầu HTTP sau:

  • Authorization – Mã thông báo uỷ quyền cho yêu cầu.

  • Content-Length – Kích thước (tính bằng byte) của nội dung chưa được tải lên. Nếu đang tải phần còn lại của tệp lên, bạn có thể tính giá trị này bằng cách trừ giá trị FIRST_BYTE khỏi giá trị TOTAL_CONTENT_LENGTH. Cả hai giá trị này đều được dùng trong tiêu đề Content-Range.

  • Content-Range – Phần tệp mà bạn đang tải lên. Giá trị tiêu đề bao gồm ba giá trị:

    • FIRST_BYTE – Chỉ mục số dựa trên 0 của số byte mà bạn đang tiếp tục tải lên. Giá trị này cao hơn một số so với số thứ hai trong tiêu đề Range được truy xuất ở bước trước. Trong ví dụ trước, giá trị tiêu đề Range0-999999, vì vậy, byte đầu tiên trong lần tải lên tiếp nối sau đó sẽ là 1000000.

    • LAST_BYTE – Chỉ mục số dựa trên 0 của byte cuối cùng trong tệp nhị phân mà bạn đang tải lên. Thông thường, đây là byte cuối cùng trong tệp. Ví dụ: nếu kích thước tệp là 3000000 byte, thì byte cuối cùng trong tệp sẽ là số 2999999.

    • TOTAL_CONTENT_LENGTH – Tổng kích thước của tệp video tính bằng byte. Giá trị này giống với tiêu đề Content-Length được chỉ định trong yêu cầu tải lên ban đầu.

    Lưu ý: Bạn không thể tải một khối không liên tục của tệp nhị phân lên. Nếu bạn cố gắng tải một khối không liên tục lên, thì nội dung nhị phân còn lại sẽ không được tải lên.

    Do đó, byte đầu tiên được tải lên trong quá trình tải lên tiếp tục phải là byte tiếp theo sau byte cuối cùng đã được tải lên thành công lên YouTube. (Xem phần thảo luận về tiêu đề Range trong bước 4.2.

    Do đó, nếu byte cuối cùng trong tiêu đề Range999999, thì byte đầu tiên trong yêu cầu tiếp tục tải lên phải là byte 1000000. (Cả hai số đều sử dụng chỉ mục dựa trên 0.) Nếu bạn cố gắng tiếp tục tải lên từ byte 999999 trở xuống (các byte trùng lặp) hoặc byte 1000001 trở lên (bỏ qua các byte), thì không có nội dung nhị phân nào được tải lên.

Tải tệp lên theo từng phần

Thay vì cố gắng tải toàn bộ tệp lên và tiếp tục tải lên trong trường hợp bị gián đoạn mạng, ứng dụng của bạn có thể chia tệp thành nhiều phần và gửi một loạt yêu cầu để tải các phần đó lên theo trình tự. Phương pháp này hiếm khi cần thiết và bạn không nên sử dụng vì nó yêu cầu các yêu cầu bổ sung, ảnh hưởng đến hiệu suất. Tuy nhiên, điều này có thể hữu ích nếu bạn đang cố gắng hiển thị chỉ báo tiến trình trên một mạng rất không ổn định.

Hướng dẫn tải tệp lên theo từng phần gần như giống với quy trình gồm 4 bước được giải thích trước đó trong hướng dẫn này. Tuy nhiên, các yêu cầu bắt đầu tải tệp lên (bước 3 ở trên) và tiếp tục tải tệp lên (bước 4.3 ở trên) đều đặt giá trị tiêu đề Content-LengthContent-Range theo cách khác nhau khi tệp đang được tải lên theo từng phần.

  • Giá trị tiêu đề Content-Length chỉ định kích thước của phần mà yêu cầu đang gửi. Hãy lưu ý các hạn chế sau đây về kích thước phân đoạn:

    • Kích thước của phần dữ liệu phải là bội số của 256 KB. (Hạn chế này không áp dụng cho phần cuối cùng vì kích thước của toàn bộ tệp không được là bội số của 256 KB.) Hãy nhớ rằng các đoạn lớn hơn sẽ hiệu quả hơn.

    • Kích thước phân đoạn phải giống nhau cho mỗi yêu cầu trong trình tự tải lên, ngoại trừ yêu cầu cuối cùng, yêu cầu này chỉ định kích thước của phân đoạn cuối cùng.

  • Tiêu đề Content-Range chỉ định số byte trong tệp mà yêu cầu đang tải lên. Bạn có thể áp dụng hướng dẫn đặt tiêu đề Content-Range ở bước 4.3 khi đặt giá trị này.

    Ví dụ: giá trị bytes 0-524287/2000000 cho biết yêu cầu đang gửi 524.288 byte đầu tiên (256 x 2048) trong tệp chứa 2.000.000 byte.

Ví dụ bên dưới cho thấy định dạng của yêu cầu đầu tiên trong một loạt yêu cầu sẽ tải tệp 2.000.000 byte lên theo từng phần:

PUT UPLOAD_URL HTTP/1.1
Authorization: Bearer AUTH_TOKEN
Content-Length: 524888
Content-Type: video/*
Content-Range: bytes 0-524287/2000000

{bytes 0-524287}

Nếu một yêu cầu khác ngoài yêu cầu cuối cùng thành công, máy chủ API sẽ phản hồi bằng một phản hồi 308 (Resume Incomplete). Định dạng phản hồi sẽ giống như định dạng được mô tả trong Bước 4.2: Xử lý phản hồi API ở trên.

Sử dụng giá trị trên được trả về trong tiêu đề Range của phản hồi API để xác định vị trí bắt đầu phần tiếp theo. Tiếp tục gửi các yêu cầu PUT, như mô tả trong Bước 4.3: Tiếp tục tải lên, để tải các phần tệp tiếp theo lên cho đến khi toàn bộ tệp được tải lên.

Khi toàn bộ tệp đã được tải lên, máy chủ sẽ phản hồi bằng mã phản hồi HTTP 201 (Created) và trả về các phần được yêu cầu của tài nguyên video mới tạo.

Nếu bất kỳ yêu cầu nào bị gián đoạn hoặc ứng dụng của bạn nhận được bất kỳ mã phản hồi 5xx nào, hãy làm theo quy trình được giải thích trong bước 4 để hoàn tất quá trình tải lên. Tuy nhiên, thay vì cố gắng tải phần còn lại của tệp lên, bạn chỉ cần tiếp tục tải các phần từ thời điểm bạn tiếp tục tải lên. Hãy nhớ kiểm tra trạng thái tải lên để xác định vị trí tiếp tục tải tệp lên. Đừng giả định rằng máy chủ đã nhận được tất cả (hoặc không nhận được) số byte đã gửi trong yêu cầu trước đó.

Lưu ý: Bạn cũng có thể yêu cầu trạng thái của một tệp tải lên đang hoạt động giữa các phân đoạn đã tải lên. (Quá trình tải lên không cần bị gián đoạn thì bạn mới có thể truy xuất trạng thái của quá trình đó.)