Przesyłanie załączników

Interfejs Gmail API umożliwia przesyłanie danych plików podczas tworzenia lub aktualizowania wersji roboczej lub wstawienia bądź wysyłania wiadomości.

Opcje przesyłania

Interfejs Gmail API umożliwia przesyłanie określonych typów danych binarnych lub multimediów. Cechy charakterystyczne danych, które można przesyłać, można określić na stronie referencyjnej dla każdej metody, która obsługuje przesyłanie multimediów:

  • Maksymalny rozmiar przesyłanego pliku: maksymalna ilość danych, które można przechowywać przy użyciu tej metody.
  • Akceptowane typy MIME multimediów: typy danych binarnych, które można przechowywać przy użyciu tej metody.

Prośby o przesłanie możesz przesyłać na różne sposoby. Za pomocą parametru żądania uploadType określ używaną metodę.

  • Proste przesyłanie: uploadType=media. Umożliwia szybkie przesyłanie mniejszych plików, np. o rozmiarze do 5 MB.
  • Przesyłanie wieloczęściowe: uploadType=multipart Aby szybko przesyłać mniejsze pliki i metadane, prześlij plik wraz z opisanymi metadanymi – wszystko w ramach jednego żądania.
  • Wznawianie przesyłania: uploadType=resumable. Umożliwia niezawodne przesyłanie danych, co jest szczególnie ważne w przypadku większych plików. Ta metoda używa żądania inicjowania sesji, które opcjonalnie może zawierać metadane. Jest to odpowiednia strategia dla większości aplikacji, ponieważ sprawdza się również w przypadku mniejszych plików i kosztuje jedno dodatkowe żądanie HTTP na przesłanie.

Do przesyłania multimediów używasz specjalnego identyfikatora URI. Metody obsługujące przesyłanie multimediów mają 2 punkty końcowe URI:

  • Identyfikator URI multimediów /upload. Format punktu końcowego przesyłania to standardowy identyfikator URI zasobów z prefiksem „/upload”. Używaj tego identyfikatora URI do przesyłania samych danych multimedialnych.

    Przykład: POST /upload/gmail/v1/users/userId/messages/send

  • Standardowy identyfikator URI zasobu dla metadanych. Jeśli zasób zawiera pola danych, służą one do przechowywania metadanych opisujących przesłany plik. Możesz użyć tego identyfikatora URI podczas tworzenia lub aktualizowania wartości metadanych.

    Przykład: POST /gmail/v1/users/userId/messages/send

Proste przesyłanie

Najprostszą metodą przesłania pliku jest przesłanie prostej prośby o jego przesłanie. Ta opcja jest dobrym rozwiązaniem, gdy:

  • Plik jest na tyle mały, że jeśli nie uda się nawiązać połączenia, ponownie prześlij go w całości.
  • Brak metadanych do wysłania. Może się tak zdarzyć, jeśli planujesz wysyłać metadane tego zasobu w osobnym żądaniu lub gdy żadne metadane nie są obsługiwane ani dostępne.

Aby użyć prostego przesyłania, wyślij żądanie POST lub PUT do identyfikatora URI /upload metody i dodaj parametr zapytania uploadType=media. Na przykład:

POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=media

Nagłówki HTTP używane podczas tworzenia prostego żądania przesyłania obejmują:

  • Content-Type. Ustaw jeden z akceptowanych typów przesyłanych danych multimedialnych, które są określone w dokumentacji interfejsu API.
  • Content-Length. Ustaw liczbę bajtów, które przesyłasz. Nie jest wymagane, jeśli używasz kodowania fragmentów.

Przykład: proste przesyłanie

Poniższy przykład pokazuje wykorzystanie prostego żądania przesyłania przez interfejs 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

Jeśli żądanie zostanie zrealizowane, serwer zwróci kod stanu HTTP 200 OK wraz ze wszystkimi metadanymi:

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
}

Przesyłanie wieloczęściowe

Jeśli masz metadane, które chcesz wysłać wraz z danymi do przesłania, możesz wysłać pojedyncze żądanie multipart/related. Jest to dobry wybór, jeśli wysyłane dane są wystarczająco małe, aby można było ponownie przesłać je w całości, gdy połączenie nie powiedzie się.

Aby korzystać z przesyłania wieloczęściowego, wyślij żądanie POST lub PUT do identyfikatora URI /upload metody i dodaj parametr zapytania uploadType=multipart, na przykład:

POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=multipart

Nagłówki HTTP najwyższego poziomu, których należy używać podczas tworzenia żądania przesyłania wieloczęściowego, to:

  • Content-Type. Ustaw wartość jako wieloczęściową/powiązaną i uwzględnij ciąg granicy używany do identyfikowania części żądania.
  • Content-Length. Ustaw łączną liczbę bajtów w treści żądania. Część multimedialna w żądaniu musi być mniejsza niż maksymalny rozmiar pliku określony w tej metodzie.

Treść żądania ma format multipart/related [RFC2387] i zawiera dokładnie 2 części. Części są określane ciągiem określającym granice, a na końcu końcowego ciągu granicznego znajdują się 2 łączniki.

Każda część żądania wieloczęściowego wymaga dodatkowego nagłówka Content-Type:

  1. Część metadanych: musi być umieszczona jako pierwsza, a Content-Type musi pasować do jednego z akceptowanych formatów metadanych.
  2. Część multimediów: musi być na drugiej pozycji, a Content-Type musi być zgodny z jednym z akceptowanych typów MIME multimediów stosowanych w metodzie.

Listę akceptowanych typów MIME multimediów dla poszczególnych metod oraz limitów rozmiarów przesyłanych plików znajdziesz w dokumentacji interfejsu API.

Uwaga: aby utworzyć lub zaktualizować tylko część metadanych bez przesyłania powiązanych danych, po prostu wyślij żądanie POST lub PUT do standardowego punktu końcowego zasobu: https://www.googleapis.com/gmail/v1/users/userId/messages/send

Przykład: przesyłanie wieloczęściowe

Poniższy przykład przedstawia wieloczęściowe żądanie przesyłania wysyłane przez interfejs 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--

Jeśli żądanie się powiedzie, serwer zwróci kod stanu HTTP 200 OK wraz ze wszystkimi metadanymi:

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
}

Przesyłanie z możliwością wznowienia

Aby zwiększyć niezawodność przesyłania plików danych, możesz użyć protokołu przesyłania wznawiania. Protokół ten umożliwia wznowienie operacji przesyłania, gdy przepływ danych zostanie przerwany przez błąd komunikacji. Jest to szczególnie przydatne, jeśli przesyłasz duże pliki, w przypadku których prawdopodobieństwo przerwy w działaniu sieci lub innej awarii przesyłania danych jest wysokie, np. podczas przesyłania z aplikacji mobilnej klienckiej. Funkcja może też zmniejszyć wykorzystanie przepustowości w przypadku awarii sieci, ponieważ nie trzeba ponownie uruchamiać dużych plików.

Aby włączyć przesyłanie z możliwością wznowienia:

  1. Rozpocznij sesję, którą można wznowić. Jeśli występują, wyślij początkowe żądanie do identyfikatora URI przesyłania zawierającego metadane.
  2. Zapisz identyfikator URI sesji możliwej do wznowienia. Zapisz identyfikator URI sesji zwrócony w odpowiedzi na pierwsze żądanie. Będziesz go używać w pozostałych żądaniach w tej sesji.
  3. Prześlij plik. Wyślij plik multimedialny do identyfikatora URI sesji możliwej do wznowienia.

Oprócz tego aplikacje, które używają przesyłania z możliwością wznowienia, muszą mieć kod umożliwiający wznowienie przerwanego przesyłania. Jeśli przesyłanie zostanie przerwane, sprawdź, ile danych zostało otrzymanych, a następnie wznów przesyłanie od tego momentu.

Uwaga: identyfikator URI przesyłania wygasa po tygodniu.

Krok 1. Rozpocznij sesję z możliwością wznowienia

Aby zainicjować wznowienie przesyłania, wyślij żądanie POST lub PUT do identyfikatora URI /upload metody i dodaj parametr zapytania uploadType=resumable, na przykład:

POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable

Treść żądania jest pusta lub zawiera tylko metadane. W kolejnych żądaniach przenosisz faktyczną zawartość pliku, który chcesz przesłać.

W początkowym żądaniu użyj tych nagłówków HTTP:

  • X-Upload-Content-Type. Ustaw typ MIME multimediów dla przesyłanych danych, które mają być przesyłane w kolejnych żądaniach.
  • X-Upload-Content-Length. Ustaw liczbę bajtów przesyłanych danych, które mają być przesyłane w kolejnych żądaniach. Jeśli w momencie przesyłania żądania długość jest nieznana, możesz pominąć ten nagłówek.
  • W przypadku podawania metadanych: Content-Type. Ustawiany jest zgodnie z typem danych metadanych.
  • Content-Length. Ustaw liczbę bajtów w treści tego początkowego żądania. Nie jest wymagane, jeśli używasz kodowania fragmentów.

Listę akceptowanych typów MIME multimediów dla poszczególnych metod oraz limitów rozmiarów przesyłanych plików znajdziesz w dokumentacji interfejsu API.

Przykład: żądanie zainicjowania sesji możliwe do wznowienia

Z przykładu poniżej dowiesz się, jak zainicjować sesję z możliwością wznowienia działania interfejsu 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
}

Uwaga: w przypadku początkowego wznowienia aktualizacji bez metadanych pozostaw treść żądania pustą i ustaw nagłówek Content-Length na 0.

Następna sekcja zawiera informacje na temat postępowania z odpowiedzią.

Krok 2. Zapisz identyfikator URI sesji możliwej do wznowienia

Jeśli żądanie inicjowania sesji się powiedzie, serwer interfejsu API w odpowiedzi wyświetli kod stanu HTTP 200 OK. Dodatkowo zawiera nagłówek Location, który określa identyfikator URI sesji, który można wznowić. Nagłówek Location, widoczny w przykładzie poniżej, zawiera fragment parametru zapytania upload_id, który podaje unikalny identyfikator przesyłania używany w tej sesji.

Przykład: odpowiedź na rozpoczęcie sesji z możliwością wznowienia

Oto odpowiedź na prośbę z kroku 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

Wartość nagłówka Location (jak w przykładowej odpowiedzi powyżej) to identyfikator URI sesji, którego będziesz używać jako punktu końcowego HTTP podczas rzeczywistego przesyłania pliku lub wysyłania zapytań dotyczących stanu przesyłania.

Skopiuj i zapisz identyfikator URI sesji, aby móc go używać w kolejnych żądaniach.

Krok 3: prześlij plik

Aby przesłać plik, wyślij żądanie PUT na identyfikator URI przesyłania uzyskany w poprzednim kroku. Takie żądanie ma format:

PUT session_uri

Nagłówki HTTP używane przy tworzeniu żądań wznowienia przesyłania plików obejmują element Content-Length. Wpisz w tym polu liczbę bajtów, które przesyłasz w ramach tego żądania, czyli zazwyczaj jest to rozmiar przesyłanego pliku.

Przykład: prośba o wznawianie przesłania pliku

Oto możliwe do wznowienia żądanie przesłania całego pliku e-mail o wielkości 2 000 000 bajtów na potrzeby obecnego przykładu.

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

Jeśli żądanie się powiedzie, serwer w odpowiedzi wyświetli HTTP 201 Created wraz ze wszystkimi metadanymi powiązanymi z tym zasobem. Jeśli początkowym żądaniem sesji możliwej do wznowienia było żądanie PUT, w celu zaktualizowania istniejącego zasobu odpowiedź powołana to 200 OK wraz z wszelkimi metadanymi powiązanymi z tym zasobem.

Jeśli żądanie przesyłania zostało przerwane albo otrzymasz od serwera odpowiedź HTTP 503 Service Unavailable lub inną odpowiedź 5xx, wykonaj czynności opisane w sekcji Wznawianie przerwanego przesyłania.  


Przesyłanie pliku partiami

Przesyłanie z możliwością wznowienia pozwala podzielić plik na fragmenty i wysłać serię żądań o przesłanie poszczególnych fragmentów. Nie jest to preferowane podejście, ponieważ dodatkowe żądania wiążą się z kosztami wydajności i zasadniczo nie są potrzebne. Może być jednak konieczne zastosowanie podziału na fragmenty, aby zmniejszyć ilość danych przesyłanych w jednym żądaniu. Jest to przydatne, gdy istnieje stały limit czasu dla poszczególnych żądań, jak ma to miejsce w przypadku niektórych klas żądań Google App Engine. W ten sposób możesz też na przykład wyświetlać wskaźniki postępu przesyłania w starszych przeglądarkach, które domyślnie nie obsługują tego procesu.


Wznawianie przerwanego przesyłania

Jeśli żądanie przesyłania zostanie zakończone przed otrzymaniem odpowiedzi lub jeśli otrzymasz z serwera odpowiedź HTTP 503 Service Unavailable, musisz wznowić przerwane przesyłanie. Aby to zrobić:

  1. Stan żądania. Sprawdzaj bieżący stan przesyłania, wysyłając puste żądanie PUT do identyfikatora URI przesyłania. W przypadku tego żądania nagłówki HTTP powinny zawierać nagłówek Content-Range wskazujący, że bieżąca pozycja w pliku jest nieznana. Jeśli na przykład łączna długość pliku wynosi 2 000 000, możesz ustawić Content-Range na */2000000. Jeśli nie znasz pełnego rozmiaru pliku, ustaw Content-Range na */*.

    Uwaga: możesz poprosić o stan między poszczególnymi fragmentami, nie tylko wtedy, gdy przesyłanie zostało przerwane. Jest to przydatne na przykład wtedy, gdy chcesz wyświetlać wskaźniki postępu przesyłania w starszych przeglądarkach.

  2. Sprawdzanie liczby przesłanych bajtów. Przetwarzanie odpowiedzi z zapytania o stan. Serwer w odpowiedzi używa nagłówka Range, aby określić, jakie bajty odebrał do tej pory. Na przykład nagłówek Range o wartości 0-299999 oznacza, że otrzymano pierwsze 300 000 bajtów pliku.
  3. Prześlij pozostałe dane. Teraz, gdy wiesz już, gdzie wznowić żądanie, wyślij pozostałe dane lub bieżący fragment. Pamiętaj, że w obu przypadkach pozostałe dane musisz traktować jako osobny fragment, więc po wznowieniu przesyłania musisz wysłać nagłówek Content-Range.
Przykład: wznawianie przerwanego przesyłania

1) Poproś o stan przesyłania.

W tym żądaniu użyto nagłówka Content-Range,aby wskazać,że bieżąca pozycja w pliku o rozmiarze 2 000 000 bajtów jest nieznana.

PUT {session_uri} HTTP/1.1
Content-Length: 0
Content-Range: bytes */2000000

2) Wyodrębnij liczbę bajtów przesłanych do tej pory z odpowiedzi.

Odpowiedź serwera używa nagłówka Range do wskazania, że odebrał pierwsze 43 bajty pliku. Użyj górnej wartości nagłówka Range, aby określić miejsce rozpoczęcia wznowienia przesyłania.

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42

Uwaga: po zakończeniu przesyłania odpowiedź o stanie może być 201 Created lub 200 OK. Może się tak zdarzyć, jeśli połączenie zostało przerwane po przesłaniu wszystkich bajtów, ale przed otrzymaniem odpowiedzi od serwera przez klienta.

3) Wznów przesyłanie od miejsca, w którym zostało przerwane.

To żądanie wznowi przesyłanie, wysyłając pozostałe bajty pliku (począwszy od 43 bajtów).

PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

Sprawdzone metody

Podczas przesyłania multimediów warto znać sprawdzone metody postępowania z błędami.

  • Wznów lub ponów próbę przesyłania, jeśli nie uda się je przesłać z powodu przerw w połączeniu lub błędów 5xx, w tym:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Użyj strategii wykładniczego ponowienia, jeśli podczas wznawiania lub ponawiania żądań przesłania zwracany jest dowolny błąd serwera 5xx. Te błędy mogą wystąpić, gdy serwer jest przeciążony. Wykładnicze opóźnienie może pomóc złagodzić tego typu problemy w okresach dużej liczby żądań lub dużego ruchu w sieci.
  • Żądania innych rodzajów nie powinny być obsługiwane przez wykładnicze ponawianie, ale nadal możesz ponawiać próby wykonania kilku z nich. Ogranicz liczbę ponownych prób. Kod może na przykład zostać ograniczony do 10 ponownych prób przed zgłoszeniem błędu.
  • Podczas wznawiania przesyłania możesz usunąć błędy 404 Not Found i 410 Gone, zaczynając od początku.

Wykładniczy czas ponowienia

Wykładniczy czas ponowienia to standardowa strategia obsługi błędów w aplikacjach sieciowych, w której klient przez dłuższy czas ponawia próbę nieudanego żądania. Jeśli duża liczba żądań lub duży ruch w sieci powoduje, że serwer zwraca błędy, dobrym rozwiązaniem w przypadku tych błędów może być wykładnicze ponawianie. Nie sprawdza się natomiast w przypadku błędów niezwiązanych z liczbą sieci lub czasem odpowiedzi, takich jak nieprawidłowe dane uwierzytelniające lub błędy „Nie znaleziono pliku”.

Poprawne wykorzystanie wykładniczego ponowienia zwiększa wydajność wykorzystania przepustowości, zmniejsza liczbę żądań wymaganych do uzyskania pomyślnej odpowiedzi i maksymalizuje przepustowość żądań w środowiskach równoczesnych.

Proces implementacji prostego wykładniczego ponowienia jest następujący:

  1. Wyślij żądanie do interfejsu API.
  2. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  3. Zaczekaj 1 sekundę + random_number_milliseconds i spróbuj ponownie.
  4. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  5. Zaczekaj 2 sekundy + random_number_milliseconds i spróbuj ponownie wysłać żądanie.
  6. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  7. Zaczekaj 4 sekundy + random_number_milliseconds i spróbuj ponownie.
  8. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  9. Zaczekaj 8 sekund + random_number_milliseconds i spróbuj ponownie.
  10. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  11. Zaczekaj 16 sekund + random_number_milliseconds i spróbuj ponownie.
  12. Zatrzymaj. Zgłoś lub zarejestruj błąd.

W powyższym procesie random_number_milliseconds to losowa liczba milisekund mniejszą lub równą 1000. Jest to konieczne, ponieważ wprowadzenie niewielkiego opóźnienia losowego pozwala bardziej równomiernie rozłożyć obciążenie i uniknąć możliwości oznaczenia serwera śladami. Wartość random_number_milliseconds musi być ponownie zdefiniowana po każdym oczekiwaniu.

Uwaga: czas oczekiwania zawsze wynosi (2 ^ n) + losowa_liczba_milisekund, gdzie n to monotonicznie rosnąca liczba całkowita zdefiniowana jako 0. Liczba całkowita n zwiększa się o 1 przy każdej iteracji (każdym żądaniu).

Algorytm kończy działanie, gdy wartość n wynosi 5. Ten limit zapobiega nieskończonemu ponawianiu prób klientów i powoduje całkowite opóźnienie (około 32 sekundy) przed uznaniem żądania za „nieodwracalny błąd”. Można użyć większej liczby ponownych prób, zwłaszcza jeśli trwa przesyłanie długiego czasu. Pamiętaj tylko, by ustawić rozsądną wartość opóźnienia na mniej niż minutę.

Przewodniki po bibliotece klienta interfejsu API