Membuat & Mengirim Email¶
Menangani Draf¶
Draf mewakili pesan yang belum terkirim dengan label sistem DRAFT yang diterapkan. Pesan yang ada dalam draf tidak dapat diedit setelah dibuat, tetapi dapat diganti. Dalam hal ini, resource draf hanyalah penampung yang menyediakan ID stabil karena ID pesan yang mendasarinya berubah setiap kali pesan diganti.
Resource pesan di dalam draf memiliki perilaku yang serupa dengan pesan lain, kecuali untuk perbedaan berikut:
Pesan draf tidak boleh memiliki label selain label sistem DRAFT.
Saat draf dikirim, draf akan otomatis dihapus dan pesan baru dengan ID yang diperbarui akan dibuat dengan label sistem SENT. Pesan ini ditampilkan dalam respons
drafts.send.
Membuat draf pesan¶
Aplikasi Anda dapat membuat draf menggunakan metode drafts.create. Proses umumnya adalah:
Buat pesan MIME yang sesuai dengan RFC 2822.
Konversi pesan ke string berenkode base64url.
Buat draf, tetapkan nilai kolom drafts.message.raw ke string yang dienkode.
Contoh kode berikut menunjukkan prosesnya.
import base64
from email.message import EmailMessage
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def gmail_create_draft():
"""Create and insert a draft email.
Print the returned draft's message and id.
Returns: Draft object, including draft id and message meta data.
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.
"""
creds, _ = google.auth.default()
try:
# create gmail api client
service = build("gmail", "v1", credentials=creds)
message = EmailMessage()
message.set_content("This is automated draft mail")
message["To"] = "gduser1@workspacesamples.dev"
message["From"] = "gduser2@workspacesamples.dev"
message["Subject"] = "Automated draft"
# encoded message
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {"message": {"raw": encoded_message}}
# pylint: disable=E1101
draft = (
service.users()
.drafts()
.create(userId="me", body=create_message)
.execute()
)
print(f'Draft id: {draft["id"]}\nDraft message: {draft["message"]}')
except HttpError as error:
print(f"An error occurred: {error}")
draft = None
return draft
if __name__ == "__main__":
gmail_create_draft()
Memperbarui draf¶
Mirip dengan pembuatan draf, untuk memperbarui draf, Anda harus menyediakan resource Draft dalam isi permintaan dengan kolom draft.message.raw disetel ke string berenkode base64url yang berisi pesan MIME. Karena pesan tidak dapat diperbarui, pesan yang ada dalam draf akan dihapus dan diganti dengan pesan MIME baru yang diberikan dalam permintaan pembaruan.
Anda dapat mengambil pesan MIME saat ini yang ada dalam draf dengan memanggil drafts.get dengan parameter format=raw.
Untuk mengetahui informasi selengkapnya, lihat drafts.update.
Mengirim draf¶
Saat mengirim draf, Anda dapat memilih untuk mengirim pesan sebagaimana adanya atau dengan pesan yang diperbarui. Jika Anda memperbarui konten draf dengan pesan baru, berikan resource Draft dalam isi permintaan drafts.send; tetapkan draft.id draf yang akan dikirim; dan tetapkan kolom draft.message.raw ke pesan MIME baru yang dienkode sebagai string berenkode base64url. Untuk mengetahui informasi selengkapnya, lihat drafts.send.
Mengirim Email¶
Ada dua cara untuk mengirim email menggunakan Gmail API:
Anda dapat mengirimkannya secara langsung menggunakan metode
messages.send.Anda dapat mengirimkannya dari draf, menggunakan metode
drafts.send.
Email dikirim sebagai string berenkode base64url dalam properti raw dari resource pesan. Alur kerja tingkat tinggi untuk mengirim email adalah:
Buat konten email dengan cara yang mudah dan encode sebagai string base64url.
Buat resource pesan baru dan tetapkan properti
rawke string base64url yang baru saja Anda buat.Panggil
messages.send, atau, jika mengirim draf,drafts.senduntuk mengirim pesan.
Detail alur kerja ini dapat bervariasi bergantung pada pilihan library klien dan bahasa pemrograman Anda.
Membuat pesan¶
Gmail API memerlukan pesan email MIME yang sesuai dengan RFC 2822 dan dienkode sebagai string base64url. Banyak bahasa pemrograman memiliki pustaka atau utilitas yang menyederhanakan proses pembuatan dan encoding pesan MIME. Contoh kode berikut menunjukkan cara membuat pesan MIME menggunakan library klien Google API untuk berbagai bahasa.
Contoh kode berikut menunjukkan cara membuat pesan MIME, mengenkode ke string base64url, dan menetapkannya ke kolom raw dari resource Message:
import base64
from email.message import EmailMessage
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def gmail_create_draft():
"""Create and insert a draft email.
Print the returned draft's message and id.
Returns: Draft object, including draft id and message meta data.
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.
"""
creds, _ = google.auth.default()
try:
# create gmail api client
service = build("gmail", "v1", credentials=creds)
message = EmailMessage()
message.set_content("This is automated draft mail")
message["To"] = "gduser1@workspacesamples.dev"
message["From"] = "gduser2@workspacesamples.dev"
message["Subject"] = "Automated draft"
# encoded message
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {"message": {"raw": encoded_message}}
# pylint: disable=E1101
draft = (
service.users()
.drafts()
.create(userId="me", body=create_message)
.execute()
)
print(f'Draft id: {draft["id"]}\nDraft message: {draft["message"]}')
except HttpError as error:
print(f"An error occurred: {error}")
draft = None
return draft
if __name__ == "__main__":
gmail_create_draft()
Membuat pesan dengan lampiran¶
Membuat pesan dengan lampiran sama seperti membuat pesan lainnya, tetapi proses mengupload file sebagai pesan MIME multi-bagian bergantung pada bahasa pemrograman. Contoh kode berikut menunjukkan kemungkinan cara membuat pesan MIME multi-bagian dengan lampiran.
Mirip dengan contoh sebelumnya, contoh ini juga menangani encoding pesan ke base64url dan menetapkannya ke kolom raw dari resource Message.
import base64
import mimetypes
import os
from email.message import EmailMessage
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def gmail_create_draft_with_attachment():
"""Create and insert a draft email with attachment.
Print the returned draft's message and id.
Returns: Draft object, including draft id and message meta data.
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.
"""
creds, _ = google.auth.default()
try:
# create gmail api client
service = build("gmail", "v1", credentials=creds)
mime_message = EmailMessage()
# headers
mime_message["To"] = "gduser1@workspacesamples.dev"
mime_message["From"] = "gduser2@workspacesamples.dev"
mime_message["Subject"] = "sample with attachment"
# text
mime_message.set_content(
"Hi, this is automated mail with attachment.Please do not reply."
)
# attachment
attachment_filename = "photo.jpg"
# guessing the MIME type
type_subtype, _ = mimetypes.guess_type(attachment_filename)
maintype, subtype = type_subtype.split("/")
with open(attachment_filename, "rb") as fp:
attachment_data = fp.read()
mime_message.add_attachment(attachment_data, maintype, subtype)
encoded_message = base64.urlsafe_b64encode(mime_message.as_bytes()).decode()
create_draft_request_body = {"message": {"raw": encoded_message}}
# pylint: disable=E1101
draft = (
service.users()
.drafts()
.create(userId="me", body=create_draft_request_body)
.execute()
)
print(f'Draft id: {draft["id"]}\nDraft message: {draft["message"]}')
except HttpError as error:
print(f"An error occurred: {error}")
draft = None
return draft
def build_file_part(file):
"""Creates a MIME part for a file.
Args:
file: The path to the file to be attached.
Returns:
A MIME part that can be attached to a message.
"""
content_type, encoding = mimetypes.guess_type(file)
if content_type is None or encoding is not None:
content_type = "application/octet-stream"
main_type, sub_type = content_type.split("/", 1)
if main_type == "text":
with open(file, "rb"):
msg = MIMEText("r", _subtype=sub_type)
elif main_type == "image":
with open(file, "rb"):
msg = MIMEImage("r", _subtype=sub_type)
elif main_type == "audio":
with open(file, "rb"):
msg = MIMEAudio("r", _subtype=sub_type)
else:
with open(file, "rb"):
msg = MIMEBase(main_type, sub_type)
msg.set_payload(file.read())
filename = os.path.basename(file)
msg.add_header("Content-Disposition", "attachment", filename=filename)
return msg
if __name__ == "__main__":
gmail_create_draft_with_attachment()
Mengirim pesan¶
Setelah membuat pesan, Anda dapat mengirimkannya dengan memberikannya di isi permintaan panggilan ke messages.send, seperti yang ditunjukkan dalam contoh berikut.
import base64
from email.message import EmailMessage
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def gmail_send_message():
"""Create and send an email message
Print the returned message id
Returns: Message object, including message id
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.
"""
creds, _ = google.auth.default()
try:
service = build("gmail", "v1", credentials=creds)
message = EmailMessage()
message.set_content("This is automated draft mail")
message["To"] = "gduser1@workspacesamples.dev"
message["From"] = "gduser2@workspacesamples.dev"
message["Subject"] = "Automated draft"
# encoded message
encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
create_message = {"raw": encoded_message}
# pylint: disable=E1101
send_message = (
service.users()
.messages()
.send(userId="me", body=create_message)
.execute()
)
print(f'Message Id: {send_message["id"]}')
except HttpError as error:
print(f"An error occurred: {error}")
send_message = None
return send_message
if __name__ == "__main__":
gmail_send_message()
Jika Anda mencoba mengirim balasan dan ingin email tersebut dikelompokkan, pastikan:
Header
SubjectcocokHeader
ReferencesdanIn-Reply-Tomengikuti standar RFC 2822.
Untuk mengetahui informasi tentang cara mengirim pesan dari draf, lihat Membuat Draf.
Mengupload Lampiran¶
Gmail API memungkinkan Anda mengupload data file saat membuat atau memperbarui draft atau saat menyisipkan atau mengirim pesan.
Opsi upload¶
Gmail API memungkinkan Anda mengupload jenis data biner atau media tertentu. Karakteristik khusus dari data yang dapat Anda upload ditetapkan di halaman referensi untuk metode apa pun yang mendukung penguploadan media:
Ukuran file upload maksimum: Jumlah maksimum data yang dapat Anda simpan dengan metode ini.
Jenis MIME media yang diperbolehkan: Jenis data biner yang dapat Anda simpan menggunakan metode ini.
Anda dapat membuat permintaan upload dengan salah satu cara berikut. Tentukan metode yang Anda gunakan dengan parameter permintaan uploadType.
Upload sederhana:
uploadType=media. Untuk mentransfer file berukuran lebih kecil dengan cepat, misalnya, 5 MB atau kurang.Upload multibagian:
uploadType=multipart. Untuk mentransfer file dan metadata berukuran lebih kecil dengan cepat; mentransfer file dengan metadata yang mendeskripsikannya, semuanya dalam satu permintaan.Upload yang dapat dilanjutkan:
uploadType=resumable. Untuk transfer yang andal, sangat penting untuk file dengan ukuran yang lebih besar. Dengan metode ini, Anda menggunakan permintaan untuk memulai sesi, yang secara opsional dapat menyertakan metadata. Ini adalah strategi yang cocok digunakan untuk kebanyakan aplikasi, karena metode ini juga dapat digunakan untuk file berukuran lebih kecil, dan hanya membutuhkan satu permintaan HTTP tambahan per upload.
Saat mengupload media, Anda menggunakan URI khusus. Kenyataannya, metode yang mendukung upload media memiliki dua endpoint URI:
URI /upload, untuk media. Format endpoint upload adalah URI resource standar dengan awalan “/upload”. Gunakan URI ini saat mentransfer data media itu sendiri.
Contoh: POST /upload/gmail/v1/users/
userId/messages/sendURI resource standar, untuk metadata. Jika resource berisi kolom data apa pun, kolom tersebut digunakan untuk menyimpan metadata yang mendeskripsikan file yang diupload. Anda dapat menggunakan URI ini saat membuat atau memperbarui nilai metadata.
Contoh: POST /gmail/v1/users/
userId/messages/send
Upload sederhana¶
Metode paling sederhana untuk mengupload file adalah dengan membuat permintaan upload sederhana. Opsi ini merupakan pilihan yang baik jika:
File cukup kecil untuk diupload lagi secara keseluruhan jika koneksi gagal.
Tidak ada metadata yang akan dikirim. Hal ini mungkin berlaku jika Anda berencana untuk mengirimkan metadata untuk resource ini dalam permintaan terpisah, atau jika tidak ada metadata yang didukung atau tersedia.
Untuk menggunakan upload sederhana, buat permintaan POST atau PUT ke URI /upload pada metode dan tambahkan parameter kueri uploadType=media. Contoh:
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=media
Header HTTP yang digunakan saat membuat permintaan upload sederhana meliputi:
Content-Type. Setel ke salah satu jenis data media upload yang diperbolehkan, yang ditentukan dalam referensi API.Content-Length. Setel ke jumlah byte yang Anda upload. Tidak diperlukan jika Anda menggunakan potongan encoding transfer.
Contoh: Upload sederhana¶
Contoh berikut menunjukkan penggunaan permintaan upload sederhana untuk Gmail API.
POST /upload/gmail/v1/users/userId/messages/send?uploadType=media HTTP/1.1
Host: www.googleapis.com
Content-Type: message/rfc822
Content-Length: number_of_bytes_in_file
Authorization: Bearer your_auth_token
Email Message data
Jika permintaan berhasil, server akan menampilkan kode status 200 OK HTTP beserta metadata apa pun:
HTTP/1.1 200
Content-Type: application/json
{
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
Upload multibagian¶
Jika memiliki metadata yang ingin dikirim dengan data yang akan diupload, Anda dapat membuat satu permintaan multipart/related. Ini adalah pilihan yang bagus jika data yang Anda kirim cukup kecil untuk diupload lagi secara keseluruhan jika koneksi gagal.
Untuk menggunakan upload multibagian, buat permintaan POST atau PUT ke URI /upload metode dan tambahkan parameter kueri uploadType=multipart, misalnya:
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=multipart
Header HTTP tingkat atas yang digunakan saat membuat permintaan upload multibagian mencakup:
Content-Type. Setel ke multibagian/terkait dan sertakan string batas yang Anda gunakan untuk mengidentifikasi bagian permintaan.Content-Length. Setel ke jumlah total byte dalam isi permintaan. Bagian media dari permintaan harus kurang dari ukuran file maksimum yang ditetapkan untuk metode ini.
Isi permintaan diformat sebagai jenis konten multipart/related [RFC2387] dan berisi tepat dua bagian. Bagian-bagian tersebut diidentifikasi oleh string batas, dan string batas akhir diikuti oleh dua tanda hubung.
Setiap bagian dari permintaan multibagian memerlukan header Content-Type tambahan:
Bagian metadata: Harus didahulukan, dan
Content-Typeharus cocok dengan salah satu format metadata yang diperbolehkan.Bagian media: Harus ada di urutan kedua, dan
Content-Typeharus cocok dengan salah satu jenis MIME media yang diperbolehkan metode ini.
Lihat referensi API untuk daftar jenis MIME media yang diperbolehkan dan batas ukuran setiap metode untuk file yang diupload.
Catatan
Untuk membuat atau memperbarui bagian metadata saja, tanpa mengupload data terkait, cukup kirim permintaan POST atau PUT ke endpoint resource standar: https://www.googleapis.com/gmail/v1/users/userId/messages/send
Contoh: Upload multibagian
Contoh di bawah ini menunjukkan permintaan upload multibagian untuk Gmail API.
POST /upload/gmail/v1/users/userId/messages/send?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body
--foo_bar_baz
Content-Type: application/json; charset=UTF-8
{
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
--foo_bar_baz
Content-Type: message/rfc822
Email Message data
--foo_bar_baz--
Jika permintaan berhasil, server akan menampilkan kode status 200 OK HTTP beserta metadata apa pun:
HTTP/1.1 200
Content-Type: application/json
{
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
Upload yang dapat dilanjutkan¶
Untuk mengupload file data dengan lebih andal, Anda dapat menggunakan protokol upload yang dapat dilanjutkan. Protokol ini memungkinkan Anda melanjutkan operasi upload setelah kegagalan komunikasi mengganggu aliran data. Protokol ini sangat berguna jika Anda mentransfer file besar dan ada kemungkinan besar terjadinya gangguan jaringan atau kegagalan transmisi lainnya, misalnya, saat mengupload dari aplikasi klien seluler. Protokol ini juga dapat mengurangi penggunaan bandwidth jika terjadi kegagalan jaringan, karena Anda tidak perlu memulai ulang proses upload file besar dari awal.
Langkah-langkah untuk menggunakan upload yang dapat dilanjutkan meliputi:
Mulai sesi yang dapat dilanjutkan. Buat permintaan awal untuk URI upload yang menyertakan metadata, jika ada.
Simpan URI sesi yang dapat dilanjutkan. Simpan URI sesi yang ditampilkan sebagai respons atas permintaan awal; Anda akan menggunakannya untuk permintaan yang tersisa dalam sesi ini.
Upload file. Kirim file media ke URI sesi yang dapat dilanjutkan.
Selain itu, aplikasi yang menggunakan upload yang dapat dilanjutkan harus memiliki kode untuk melanjutkan upload yang terhenti. Jika upload terhenti, cari tahu berapa banyak data yang berhasil diterima, lalu lanjutkan upload mulai dari titik tersebut.
Catatan
masa berlaku URI upload akan berakhir setelah satu minggu.
Langkah 1: Mulai sesi yang dapat dilanjutkan¶
Untuk memulai upload yang dapat dilanjutkan, buat permintaan POST atau PUT ke URI /upload metode dan tambahkan parameter kueri uploadType=resumable, misalnya:
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable
Untuk permintaan memulai ini, bagian isi akan kosong atau hanya berisi metadata; Anda akan mentransfer konten yang sebenarnya dari file yang ingin diupload dalam permintaan berikutnya.
Gunakan header HTTP berikut dengan permintaan awal:
X-Upload-Content-Type. Setel ke jenis MIME media dari data upload yang akan ditransfer dalam permintaan berikutnya.X-Upload-Content-Length. Setel ke jumlah byte data upload yang akan ditransfer dalam permintaan berikutnya. Jika panjang tidak diketahui pada saat permintaan ini, Anda dapat menghilangkan header ini.Jika menyediakan metadata: Content-Type. Setel sesuai dengan jenis data metadata.
Content-Length. Setel ke jumlah byte yang diberikan dalam isi permintaan awal ini. Tidak diperlukan jika Anda menggunakan potongan encoding transfer.
Lihat referensi API untuk daftar jenis MIME media yang diperbolehkan dan batas ukuran setiap metode untuk file yang diupload.
Contoh: Permintaan untuk memulai sesi yang dapat dilanjutkan
Contoh berikut menunjukkan cara memulai sesi yang dapat dilanjutkan untuk Gmail API.
POST /upload/gmail/v1/users/userId/messages/send?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: message/rfc822
X-Upload-Content-Length: 2000000
{
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
Catatan
Untuk permintaan update awal yang dapat dilanjutkan tanpa metadata, biarkan isi permintaan dalam keadaan kosong, dan setel header Content-Length ke 0.
Bagian selanjutnya menjelaskan cara menangani respons.
Langkah 2: Simpan URI sesi yang dapat dilanjutkan¶
Jika permintaan untuk memulai sesi berhasil, server API akan merespons dengan kode status HTTP 200 OK. Selain itu, server API memberikan header Location yang menentukan URI sesi yang dapat dilanjutkan. Header Location, yang ditunjukkan pada contoh di bawah, menyertakan bagian parameter kueri upload_id yang memberikan ID upload unik untuk digunakan pada sesi ini.
Contoh: Respons memulai sesi yang dapat dilanjutkan
Berikut adalah respons terhadap permintaan pada Langkah 1:
HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0
Nilai header Location, seperti yang ditunjukkan pada contoh respons di atas, adalah URI sesi yang akan Anda gunakan sebagai endpoint HTTP untuk melakukan upload file sebenarnya atau membuat kueri status upload.
Salin dan simpan URI sesi sehingga Anda dapat menggunakannya untuk permintaan berikutnya.
Langkah 3: Upload file¶
Untuk mengupload file, kirim permintaan PUT ke URI upload yang Anda dapatkan di langkah sebelumnya. Format permintaan upload adalah:
PUT session_uri
Header HTTP yang akan digunakan saat membuat permintaan upload file yang dapat dilanjutkan meliputi Content-Length. Setel ini ke jumlah byte yang Anda upload dalam permintaan ini, yang umumnya merupakan ukuran file upload.
Contoh: Permintaan upload file yang dapat dilanjutkan
Berikut adalah permintaan yang dapat dilanjutkan guna mengupload seluruh file Pesan Email 2.000.000 byte untuk contoh ini.
PUT https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: message/rfc822
bytes 0-1999999
Jika permintaan berhasil, server merespons dengan HTTP 201 Created, beserta metadata apa pun yang terkait dengan resource ini. Jika permintaan awal sesi yang dapat dilanjutkan adalah PUT, untuk memperbarui resource yang ada, respons suksesnya adalah 200 OK, beserta metadata apa pun yang terkait dengan resource ini.
Jika permintaan upload terhenti atau jika Anda menerima respons HTTP 503 Service Unavailable atau 5xx lainnya dari server, ikuti prosedur yang diuraikan dalam melanjutkan upload yang terhenti.
Mengupload file dalam potongan
Dengan upload yang dapat dilanjutkan, Anda dapat membagi file menjadi potongan-potongan dan mengirim serangkaian permintaan untuk mengupload setiap potongan secara berurutan. Ini bukan pendekatan yang disarankan karena ada biaya performa terkait permintaan tambahan, dan biasanya tidak diperlukan. Namun, Anda mungkin perlu menggunakan pemotongan untuk mengurangi jumlah data yang ditransfer dalam satu permintaan. Ini akan berguna apabila ada batas waktu tetap untuk masing-masing permintaan, seperti halnya untuk kelas tertentu dari permintaan Google App Engine. Ini juga memungkinkan Anda melakukan hal-hal seperti memberikan indikasi progres upload untuk browser lama yang tidak memiliki dukungan progres upload secara default.
Jika Anda mengupload data dalam beberapa potongan, header Content-Range juga diperlukan, beserta header Content-Length yang diperlukan untuk upload file lengkap:
Content-Length. Setel ke ukuran potongan atau yang lebih kecil, yang mungkin berlaku untuk permintaan terakhir.Content-Range: Setel untuk menampilkan byte mana dalam file yang Anda upload. Misalnya,Content-Range: bytes 0-524287/2000000menunjukkan bahwa Anda memberikan 524.288 byte pertama (256 x 1024 x 2) dalam file 2.000.000 byte.
Tip
Pembatasan ukuran potongan: Semua potongan harus berukuran kelipatan 256 KB (256 x 1024 byte), kecuali untuk potongan terakhir yang menyelesaikan proses upload. Jika Anda menggunakan pemotongan, penting untuk menjaga ukuran potongan sebesar mungkin agar proses upload tetap efisien.
Contoh: Permintaan upload file potongan yang dapat dilanjutkan
Permintaan yang mengirimkan 524.288 byte pertama mungkin terlihat seperti ini:
PUT {session_uri} HTTP/1.1
Host: www.googleapis.com
Content-Length: 524288
Content-Type: message/rfc822
Content-Range: bytes 0-524287/2000000
bytes 0-524288
Jika permintaan berhasil, server merespons dengan 308 Resume Incomplete, beserta header Range yang mengidentifikasi total jumlah byte yang telah disimpan sejauh ini:
HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: bytes=0-524287
Gunakan nilai yang lebih besar yang ditampilkan dalam header Range untuk menentukan tempat memulai potongan berikutnya. Lanjutkan untuk melakukan PUT pada setiap bagian file hingga seluruh file diupload.
Jika ada permintaan PUT potongan yang terhenti atau jika Anda menerima respons 503 Service Unavailable HTTP atau respons 5xx lain dari server, ikuti prosedur yang diuraikan dalam melanjutkan upload yang terhenti. Namun, cukup lanjutkan mengupload potongan dari titik tersebut, bukan mengupload sisa file.
Catatan Penting:
Pastikan untuk menggunakan header
Rangedalam respons untuk menentukan tempat memulai potongan berikutnya; jangan berasumsi bahwa server menerima semua byte yang dikirim dalam permintaan sebelumnya.Setiap URI upload memiliki masa berlaku yang terbatas dan akan berakhir (dalam waktu sekitar satu hari, jika tidak digunakan). Karena alasan ini, sebaiknya mulai upload yang dapat dilanjutkan segera setelah Anda mendapatkan URI upload, dan lanjutkan upload yang terhenti segera setelah terjadi gangguan.
Jika Anda mengirimkan permintaan dengan ID sesi upload yang sudah tidak berlaku lagi, server akan menampilkan kode status
404 Not Found. Saat terjadi error yang tidak dapat dipulihkan dalam sesi upload, server akan menampilkan kode status410 Gone. Dalam kasus ini, Anda harus memulai upload dapat dilanjutkan yang baru, mendapatkan URI upload baru, dan memulai upload dari awal menggunakan endpoint baru.
Saat seluruh upload file selesai, server merespons dengan HTTP 201 Created beserta metadata apa pun yang terkait dengan resource ini. Jika permintaan ini memperbarui entitas yang sudah ada, dan bukan membuat entitas baru, kode respons HTTP untuk upload yang selesai adalah 200 OK.
Melanjutkan upload yang terhenti
Jika permintaan upload dihentikan sebelum menerima respons atau jika Anda menerima respons 503 Service Unavailable HTTP dari server, maka Anda perlu melanjutkan upload yang terhenti. Untuk melakukan ini:
Status permintaan. Buat kueri status upload saat ini dengan mengajukan permintaan PUT kosong ke URI upload. Untuk permintaan ini, header HTTP harus menyertakan header
Content-Rangeyang menunjukkan bahwa posisi saat ini pada file tidak diketahui. Misalnya, setel Content-Range ke*/2000000jika total panjang file adalah 2.000.000. Jika Anda tidak mengetahui ukuran penuh file, setelContent-Rangeke*/*.Catatan
Anda dapat meminta status di antara setiap potongan, bukan hanya jika upload terganggu. Tindakan ini berguna, misalnya, jika Anda ingin menampilkan indikasi progres upload untuk browser lama.
Dapatkan jumlah byte yang diupload. Proses respons dari kueri status. Server menggunakan header
Rangedalam responsnya untuk menentukan byte yang telah diterima sejauh ini. Misalnya, header Range dari0-299999menunjukkan bahwa 300.000 byte pertama file telah diterima.Upload data yang tersisa. Terakhir, setelah Anda mengetahui tempat untuk melanjutkan permintaan, kirim data yang tersisa atau potongan saat ini. Perhatikan bahwa Anda harus memperlakukan data yang tersisa sebagai potongan terpisah dalam kedua kasus tersebut, jadi Anda harus mengirim header
Content-Rangesaat melanjutkan upload.
Contoh: Melanjutkan upload yang terhenti
Minta status upload.
Permintaan berikut menggunakan header
Content-Rangeuntuk menunjukkan bahwa posisi saat ini dalam file 2.000.000 byte tidak diketahui.PUT {session_uri} HTTP/1.1 Content-Length: 0 Content-Range: bytes */2000000
Ekstrak jumlah byte yang diupload sejauh ini dari respons.
Respons server menggunakan header
Rangeuntuk menunjukkan bahwa server sejauh ini telah menerima 43 byte pertama dari file. Gunakan nilai yang lebih tinggi dari headerRangeuntuk menentukan tempat memulai upload yang dilanjutkan.HTTP/1.1 308 Resume Incomplete Content-Length: 0 Range: 0-42
Catatan
Mungkin saja respons statusnya adalah 201 Created atau 200 OK jika upload selesai. Hal ini bisa terjadi jika koneksi terputus setelah semua byte diupload tetapi sebelum klien menerima respons dari server.
Lanjutkan upload dari titik terakhir upload sebelumnya.
Permintaan berikut melanjutkan upload dengan mengirimkan byte file yang tersisa, mulai byte 43.
PUT {session_uri} HTTP/1.1 Content-Length: 1999957 Content-Range: bytes 43-1999999/2000000 bytes 43-1999999
Praktik terbaik¶
Saat mengupload media, sebaiknya perhatikan beberapa praktik terbaik terkait penanganan error.
Lanjutkan atau coba lagi upload yang gagal karena gangguan koneksi atau error
5xx, termasuk:500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
Gunakan strategi backoff eksponensial jika error server
5xxapa pun ditampilkan saat melanjutkan atau mencoba lagi permintaan upload. Error ini dapat terjadi jika server mengalami kelebihan beban. Backoff eksponensial dapat membantu mengurangi masalah semacam ini selama periode permintaan yang tinggi atau traffic jaringan yang tinggi.Jenis permintaan lain seharusnya tidak ditangani oleh backoff eksponensial, tetapi Anda masih bisa mencoba kembali beberapa darinya. Saat mencoba kembali permintaan ini, batasi frekuensi Anda mencoba lagi. Misalnya, kode Anda dapat dibatasi hingga sepuluh percobaan ulang atau kurang sebelum melaporkan error.
Tangani error
404 Not Founddan410 Gonesaat melakukan upload yang dapat dilanjutkan dengan memulai seluruh upload dari awal.
Backoff eksponensial¶
Backoff eksponensial adalah strategi penanganan error standar untuk aplikasi jaringan, yang mana klien secara berkala mencoba lagi permintaan yang gagal, dengan menambah lamanya penundaan antara setiap permintaan yang gagal. Jika volume permintaan yang tinggi atau traffic jaringan yang tinggi menyebabkan server menampilkan error, backoff eksponensial mungkin merupakan strategi yang tepat untuk menangani error tersebut. Sebaliknya, ini bukan strategi yang relevan untuk menangani error yang tidak terkait dengan volume jaringan atau waktu respons, seperti kredensial otorisasi yang tidak valid atau error file tidak ditemukan.
Jika digunakan dengan benar, backoff eksponensial akan meningkatkan efisiensi penggunaan bandwidth, mengurangi jumlah permintaan yang diperlukan untuk mendapatkan respons yang berhasil, dan memaksimalkan throughput permintaan dalam lingkungan serentak.
Alur untuk mengimplementasikan backoff eksponensial sederhana adalah sebagai berikut:
Buat permintaan ke API.
Terima respons
HTTP 503, yang menunjukkan bahwa Anda harus mencoba lagi permintaan tersebut.Tunggu 1 detik + random_number_milliseconds dan coba lagi permintaan tersebut.
Terima respons
HTTP 503, yang menunjukkan bahwa Anda harus mencoba lagi permintaan tersebut.Tunggu 2 detik + random_number_milliseconds dan coba lagi permintaan tersebut.
Terima respons
HTTP 503, yang menunjukkan bahwa Anda harus mencoba lagi permintaan tersebut.Tunggu 4 detik + random_number_milliseconds dan coba lagi permintaan tersebut.
Terima respons
HTTP 503, yang menunjukkan bahwa Anda harus mencoba lagi permintaan tersebut.Tunggu 8 detik + random_number_milliseconds dan coba lagi permintaan tersebut.
Terima respons
HTTP 503, yang menunjukkan bahwa Anda harus mencoba lagi permintaan tersebut.Tunggu 16 detik + random_number_milliseconds dan coba lagi permintaan tersebut.
Stop. Laporkan atau buat log untuk error.
Pada alur di atas, random_number_milliseconds adalah angka acak milidetik yang kurang dari atau sama dengan 1.000. Ini diperlukan, karena memperkenalkan penundaan acak yang singkat akan membantu mendistribusikan beban dengan lebih merata dan menghindari kemungkinan penyerbuan server. Nilai random_number_milliseconds harus ditentukan ulang setelah setiap periode tunggu.
Catatan
Periode tunggu selalu (2 ^ n) + random_number_milliseconds, yang mana n adalah bilangan bulat yang meningkat secara monotonik, yang awalnya ditetapkan sebagai 0. Integer n ditambah dengan 1 untuk setiap iterasi (setiap permintaan).
Algoritma disetel untuk dihentikan jika n adalah 5. Batas ini mencegah agar klien tidak terus mencoba tanpa batas, dan mengakibatkan penundaan total sekitar 32 detik sebelum permintaan dianggap "error yang tidak dapat dipulihkan". Jumlah percobaan ulang maksimum yang lebih besar tidak masalah, terutama jika upload yang panjang sedang berlangsung; tetapi pastikan untuk membatasi penundaan percobaan ulang pada jumlah yang masuk akal, misalnya, kurang dari satu menit.