Upload media

Mengupload item media adalah proses dua langkah:

  1. Upload byte file media Anda ke Server Google menggunakan endpoint upload. Tindakan ini akan menampilkan token upload yang mengidentifikasi byte yang diupload.
  2. Gunakan panggilan batchCreate dengan token upload untuk membuat item media di akun Google Foto pengguna.

Langkah-langkah ini menguraikan proses upload item media tunggal. Jika Anda mengupload beberapa item media (kemungkinan besar untuk aplikasi produksi), tinjau praktik terbaik upload untuk meningkatkan efisiensi upload.

Sebelum memulai

Cakupan otorisasi yang diperlukan

Mengupload item media ke galeri foto atau album pengguna memerlukan photoslibrary.appendonly atau cakupan photoslibrary.

Item media juga dapat dibuat menggunakan cakupan photoslibrary.sharing. Kepada membuat item dengan cakupan photoslibrary.sharing, Anda harus terlebih dahulu membuat dan tandai sebagai dibagikan menggunakan shareAlbum. Anda dapat membuat item media yang dibagikan dengan pengguna di album. Anda tidak dapat membuat item secara langsung di koleksi pengguna atau di album yang belum dibagikan oleh aplikasi Anda.

Saat mencantumkan album, properti isWriteable menunjukkan apakah memiliki akses untuk membuat media dalam album tertentu.

Jenis dan ukuran file yang diterima

Anda dapat mengupload jenis file yang tercantum dalam tabel di bawah.

Jenis media Jenis file yang diterima Ukuran file maksimum
Foto AVIF, BMP, GIF, HEIC, ICO, JPG, PNG, TIFF, WEBP, beberapa file RAW. 200 MB
Video 3GP, 3G2, ASF, AVI, DIVX, M2T, M2TS, M4V, MKV, MMV, MOD, MOV, MP4, MPG, MTS, TOD, WMV. 20 GB

Langkah 1: Mengupload byte

Mengupload byte ke Google menggunakan permintaan upload. Permintaan upload yang berhasil menampilkan token upload dalam bentuk string teks mentah. Gunakan upload ini token untuk membuat item media dengan panggilan batchCreate.

REST

Sertakan kolom berikut di header permintaan POST:

Kolom header
Content-type Tetapkan ke application/octet-stream.
X-Goog-Upload-Content-Type Direkomendasikan. Tetapkan ke jenis MIME byte yang Anda upload. Jenis MIME umum mencakup image/jpeg, image/png, dan image/gif.
X-Goog-Upload-Protocol Tetapkan ke raw.

Berikut adalah header permintaan POST:

POST https://photoslibrary.googleapis.com/v1/uploads
Authorization: Bearer oauth2-token
Content-type: application/octet-stream
X-Goog-Upload-Content-Type: mime-type
X-Goog-Upload-Protocol: raw

Dalam isi permintaan, sertakan biner file:

media-binary-data

Jika permintaan POST ini berhasil, token upload yang ada dalam bentuk dari string teks mentah, dikembalikan sebagai isi respons. Untuk membuat media item, gunakan string teks ini dalam panggilan batchCreate.

upload-token

Java

// Open the file and automatically close it after upload
try (RandomAccessFile file = new RandomAccessFile(pathToFile, "r")) {
  // Create a new upload request
  UploadMediaItemRequest uploadRequest =
      UploadMediaItemRequest.newBuilder()
              // The media type (e.g. "image/png")
              .setMimeType(mimeType)
              // The file to upload
              .setDataFile(file)
          .build();
  // Upload and capture the response
  UploadMediaItemResponse uploadResponse = photosLibraryClient.uploadMediaItem(uploadRequest);
  if (uploadResponse.getError().isPresent()) {
    // If the upload results in an error, handle it
    Error error = uploadResponse.getError().get();
  } else {
    // If the upload is successful, get the uploadToken
    String uploadToken = uploadResponse.getUploadToken().get();
    // Use this upload token to create a media item
  }
} catch (ApiException e) {
  // Handle error
} catch (IOException e) {
  // Error accessing the local file
}

PHP

try {
    // Create a new upload request by opening the file
    // and specifying the media type (e.g. "image/png")
    $uploadToken = $photosLibraryClient->upload(file_get_contents($localFilePath), null, $mimeType);
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
    // Handle error
}

Ukuran file yang disarankan untuk gambar kurang dari 50 MB. File yang berukuran di atas 50 MB rentan terhadap masalah performa.

Google Photos Library API mendukung upload yang dapat dilanjutkan. Dapat dilanjutkan memungkinkan Anda membagi file media menjadi beberapa bagian dan menguploadnya bagian pada satu waktu.

Langkah 2: Membuat item media

Setelah mengupload byte file media, Anda dapat membuatnya sebagai media item di Google Foto menggunakan token upload. Token upload valid selama satu hari setelah dibuat. Item media selalu ditambahkan ke library. Item media hanya dapat ditambahkan ke album yang dibuat oleh aplikasi Anda. Untuk mengetahui informasi selengkapnya, lihat Cakupan otorisasi.

Untuk membuat item media baru, panggil mediaItems.batchCreate dengan menentukan daftar newMediaItems. Setiap newMediaItem berisi upload token yang ditentukan di dalam simpleMediaItem, dan deskripsi opsional yang ditampilkan kepada pengguna.

Bidang deskripsi dibatasi hingga 1.000 karakter dan hanya boleh berisi teks yang bermakna yang dibuat oleh pengguna. Misalnya, "Perjalanan kita ke taman" atau "Makan malam liburan". Jangan sertakan metadata seperti nama file, permintaan terprogram {i>tag<i}, atau teks lainnya yang dibuat secara otomatis.

Untuk performa terbaik, kurangi jumlah panggilan ke mediaItems.batchCreate lakukan dengan menyertakan beberapa item media dalam satu panggilan. Selalu tunggu hingga permintaan sebelumnya selesai sebelum melakukan panggilan berikutnya untuk pengguna yang sama.

Anda dapat membuat satu item media atau beberapa item media di koleksi pengguna dengan menentukan deskripsi dan token upload yang sesuai:

REST

Berikut adalah header permintaan POST:

POST https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate
Content-type: application/json
Authorization: Bearer oauth2-token

Isi permintaan harus menentukan daftar newMediaItems.

{
  "newMediaItems": [
    {
      "description": "item-description",
      "simpleMediaItem": {
        "fileName": "filename",
        "uploadToken": "upload-token"
      }
    }
   , ...
  ]
}

Java

try {
  // Create a NewMediaItem with the following components:
  // - uploadToken obtained from the previous upload request
  // - filename that will be shown to the user in Google Photos
  // - description that will be shown to the user in Google Photos
  NewMediaItem newMediaItem = NewMediaItemFactory
          .createNewMediaItem(uploadToken, fileName, itemDescription);
  List<NewMediaItem> newItems = Arrays.asList(newMediaItem);

  BatchCreateMediaItemsResponse response = photosLibraryClient.batchCreateMediaItems(newItems);
  for (NewMediaItemResult itemsResponse : response.getNewMediaItemResultsList()) {
    Status status = itemsResponse.getStatus();
    if (status.getCode() == Code.OK_VALUE) {
      // The item is successfully created in the user's library
      MediaItem createdItem = itemsResponse.getMediaItem();
    } else {
      // The item could not be created. Check the status and try again
    }
  }
} catch (ApiException e) {
  // Handle error
}

PHP

try {
    $newMediaItems = [];
    // Create a NewMediaItem with the following components:
    // - uploadToken obtained from the previous upload request
    // - filename that will be shown to the user in Google Photos
    // - description that will be shown to the user in Google Photos
    $newMediaItems[0] = PhotosLibraryResourceFactory::newMediaItemWithDescriptionAndFileName(
            $uploadToken, $itemDescription, $fileName);

    $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems);
    foreach ($response->getNewMediaItemResults() as $itemResult) {
        $status = $itemResult->getStatus();
        if ($status->getCode() != Code::OK) {
            // Error while creating the item.
        }
    }
} catch (\Google\ApiCore\ApiException $e) {
    // Handle error
}


Anda dapat menambahkan item media ke koleksi dan album dengan menentukan album id. Untuk informasi selengkapnya, lihat Buat album.

Setiap album dapat berisi hingga 20.000 item media. Permintaan untuk membuat media item dalam album yang melebihi batas ini akan gagal.

REST

{
  "albumId": "album-id",
  "newMediaItems": [
    {
      "description": "item-description",
      "simpleMediaItem": {
        "fileName": "filename",
        "uploadToken": "upload-token"
      }
    }
   , ...
  ]
}

Java

try {
  // Create new media items in a specific album
  BatchCreateMediaItemsResponse response = photosLibraryClient
      .batchCreateMediaItems(albumId, newItems);
  // Check the response
} catch (ApiException e) {
  // Handle error
}

PHP

try {
    $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems, ['albumId' => $albumId]);
} catch (\Google\ApiCore\ApiException $e) {
    // Handle error
}

Anda juga dapat menentukan albumId dan albumPosition untuk sisipkan item media di lokasi tertentu dalam album.

REST

{
  "albumId": "album-id",
  "newMediaItems": [
    {
      "description": "item-description",
      "simpleMediaItem": {
        "fileName": "filename",
        "uploadToken": "upload-token"
      }
    }
    , ...
  ],
  "albumPosition": {
    "position": "after-media-item",
    "relativeMediaItemId": "media-item-id"
  }
}

Java

try {
  // Create new media items in a specific album, positioned after a media item
  AlbumPosition positionInAlbum = AlbumPositionFactory.createFirstInAlbum();
  BatchCreateMediaItemsResponse response = photosLibraryClient
      .batchCreateMediaItems(albumId, newItems, positionInAlbum);
  // Check the response
} catch (ApiException e) {
  // Handle error
}

PHP

try {
    $albumPosition = PhotosLibraryResourceFactory::albumPositionAfterMediaItem($mediaItemId);
    $response = $photosLibraryClient->batchCreateMediaItems($newMediaItems,
        ['albumId' => $albumId, 'albumPosition' => $albumPosition]);
} catch (\Google\ApiCore\ApiException $e) {
    // Handle error
}

Untuk detail selengkapnya terkait pemosisian dalam album, lihat Tambahkan pengayaan.

Respons pembuatan item

Panggilan mediaItems.batchCreate menampilkan hasil untuk setiap item media Anda coba buat. Daftar newMediaItemResults menunjukkan status dan menyertakan uploadToken untuk permintaan. Kode status bukan nol mengindikasikan {i>error<i}.

REST

Jika semua item media berhasil dibuat, permintaan akan menampilkan Status HTTP 200 OK. Jika beberapa item media tidak dapat dibuat, permintaan menampilkan status HTTP 207 MULTI-STATUS untuk menunjukkan keberhasilan parsial.

{
  "newMediaItemResults": [
    {
      "uploadToken": "upload-token",
      "status": {
        "message": "Success"
      },
      "mediaItem": {
        "id": "media-item-id",
        "description": "item-description",
        "productUrl": "https://photos.google.com/photo/photo-path",
        "mimeType": "mime-type",
        "mediaMetadata": {
          "width": "media-width-in-px",
          "height": "media-height-in-px",
          "creationTime": "creation-time",
          "photo": {}
        },
        "filename": "filename"
      }
    },
    {
      "uploadToken": "upload-token",
      "status": {
        "code": 13,
        "message": "Internal error"
      }
    }
  ]
}

Java

BatchCreateMediaItemsResponse response = photosLibraryClient.batchCreateMediaItems(newItems);

// The response contains a list of NewMediaItemResults
for (NewMediaItemResult result : response.getNewMediaItemResultsList()) {
  // Each result item is identified by its uploadToken
  String uploadToken = result.getUploadToken();
  Status status = result.getStatus();

  if (status.getCode() == Code.OK_VALUE) {
    // If the request is successful, a MediaItem is returned
    MediaItem mediaItem = result.getMediaItem();
    String id = mediaItem.getId();
    String productUrl = mediaItem.getProductUrl();
    // ...
  }
}

PHP

// The response from a call to batchCreateMediaItems returns a list of NewMediaItemResults
foreach ($response->getNewMediaItemResults() as $itemResult) {
    // Each result item is identified by its uploadToken
    $itemUploadToken = $itemResult->getUploadToken();
    // Verify the status of each entry to ensure that the item has been uploaded correctly
    $itemStatus = $itemResult->getStatus();
    if ($itemStatus->getCode() != Code::OK) {
        // Error when item is being created
    } else {
        // Media item is successfully created
        // Get the MediaItem object from the response
        $mediaItem = $itemResult->getMediaItem();
        // It contains details such as the Id of the item, productUrl
        $id = $mediaItem->getId();
        $productUrl = $mediaItem->getProductUrl();
        // ...
    }
}

Jika item berhasil ditambahkan, mediaItem akan ditampilkan yang berisi elemen tersebut mediaItemId, productUrl, dan mediaMetadata. Untuk informasi selengkapnya, lihat Mengakses item media.

Jika item media adalah video, item media tersebut harus diproses terlebih dahulu. mediaItem berisi status di dalam mediaMetadata yang menjelaskan pemrosesan status file video. File yang baru diupload akan menampilkan status PROCESSING pertama, sebelum READY untuk digunakan. Untuk mengetahui detailnya, lihat Mengakses item media.

Jika Anda mengalami error selama panggilan ini, ikuti Praktik terbaik dan coba lagi permintaan Anda. Anda mungkin ingin melacak penambahan yang berhasil, sehingga gambar dapat disisipkan ke dalam album di posisi yang benar saat permintaan berikutnya. Untuk selengkapnya informasi, lihat Buat album.

Hasil selalu ditampilkan dalam urutan yang sama dengan token upload yang dikirimkan.

Praktik terbaik untuk upload

Praktik terbaik dan referensi berikut membantu meningkatkan efisiensi Anda secara keseluruhan dengan upload:

  • Gunakan salah satu library klien yang didukung.
  • Ikuti praktik terbaik penanganan error dan percobaan ulang, perhatikan poin-poin berikut:
    • Error 429 dapat terjadi jika kuota Anda telah habis atau Anda dikenai pembatasan kapasitas karena melakukan terlalu banyak panggilan terlalu cepat. Pastikan Anda tidak memanggil batchCreate untuk pengguna yang sama hingga telah selesai.
    • Error 429 memerlukan penundaan minimum 30s sebelum mencoba lagi. Gunakan backoff eksponensial saat mencoba ulang permintaan.
    • Error 500 terjadi saat server mengalami error. Saat mengupload, kemungkinan besar ini terjadi karena Anda melakukan beberapa panggilan tulis (seperti batchCreate) untuk pengguna yang sama secara bersamaan. Periksa detail permintaan Anda dan tidak melakukan panggilan ke batchCreate secara paralel.
  • Gunakan alur upload yang dapat dilanjutkan untuk membuat upload Anda lebih handal jika terjadi gangguan jaringan, sehingga penggunaan bandwidth dengan memungkinkan Anda melanjutkan upload yang selesai sebagian. Hal ini penting saat mengupload dari perangkat seluler klien, atau saat mengunggah file berukuran besar.

Selain itu, pertimbangkan tips berikut untuk setiap langkah proses upload: mengupload byte, lalu membuat item media.

Mengupload byte

  • Mengupload byte (untuk mengambil token upload) dapat dilakukan secara paralel.
  • Selalu tetapkan jenis MIME yang benar di header X-Goog-Upload-Content-Type untuk setiap panggilan upload.

Membuat item media

  • Jangan melakukan panggilan secara paralel dengan batchCreate untuk satu pengguna.

    • Untuk setiap pengguna, lakukan panggilan ke batchCreate satu per satu (di serial).
    • Untuk beberapa pengguna, selalu lakukan panggilan batchCreate untuk setiap pengguna satu demi satu. Hanya lakukan panggilan untuk pengguna yang berbeda secara paralel.
  • Sertakan sebanyak mungkin NewMediaItems di setiap panggilan ke batchCreate untuk meminimalkan jumlah total panggilan yang Anda miliki lakukan. Anda dapat menyertakan maksimal 50 item.

  • Tetapkan teks deskripsi yang bermakna yang dibuat oleh pengguna Anda. Jangan sertakan metadata seperti nama file, tag terprogram, atau teks lainnya yang dibuat secara otomatis di kolom deskripsi.

Contoh panduan

Contoh ini menggunakan kode semu untuk memandu proses upload item media untuk beberapa pelanggan. Tujuannya adalah untuk menguraikan kedua langkah proses upload (mengupload file byte dan membuat item media) serta menjelaskan praktik terbaik untuk membuat proses upload yang efisien dan tangguh integrasi.

Langkah 1: Upload byte mentah

Pertama-tama buat antrean untuk mengunggah byte mentah untuk item media Anda dari semua pelanggan. Lacak setiap uploadToken yang ditampilkan per pengguna. Ingatlah poin-poin penting berikut:

  • Jumlah rangkaian pesan upload yang serentak bergantung pada operasi Anda lingkungan fleksibel App Engine.
  • Pertimbangkan untuk mengurutkan ulang antrean upload sesuai kebutuhan. Misalnya, Anda dapat memprioritaskan upload berdasarkan jumlah upload yang tersisa per pengguna, kemajuan pengguna secara keseluruhan, atau persyaratan lainnya.

Kode semu

CREATE uploadQueue FROM users, filesToUpload
// Upload media bytes in parallel.
START multiple THREADS
  WHILE uploadQueue is not empty
    POP uploadQueue
    UPLOAD file for user
    GET uploadToken
    CHECK and HANDLE errors
    STORE uploadToken for user in uploadTokensQueue
  END

Langkah 2: Buat item media

Pada langkah 1, Anda dapat mengupload beberapa byte dari banyak pengguna secara paralel, tetapi di langkah 2, Anda hanya dapat melakukan satu panggilan untuk setiap pengguna pada satu waktu.

Kode semu

// For each user, create media items once 50 upload tokens have been
// saved, or no more uploads are left per user.
WHEN uploadTokensQueue for user is >= 50 OR no more pending uploads for user
  // Calls can be made in parallel for different users,
  // but only make a single call per user at a time.
  START new thread for (this) user if there is no thread yet
    POP 50 uploadTokens from uploadTokensQueue for user
    CALL mediaItems.batchCreate with uploadTokens
    WAIT UNTIL batchCreate call has completed
    CHECK and HANDLE errors (retry as needed)
  DONE.

Lanjutkan proses ini hingga semua upload dan panggilan pembuatan media selesai.