Ringkasan API Blobstore untuk layanan paket lama

API Blobstore memungkinkan aplikasi Anda menyajikan objek data, yang disebut blob, dengan ukuran yang jauh lebih besar dari ukuran yang diizinkan untuk objek dalam layanan Datastore. Blob berguna untuk menyajikan file besar, seperti file video atau gambar, dan untuk memungkinkan pengguna mengupload file data berukuran besar. Blob dibuat dengan mengupload file melalui permintaan HTTP. Biasanya, aplikasi Anda akan melakukannya dengan menampilkan formulir yang berisi kolom upload file kepada pengguna. Saat formulir dikirimkan, Blobstore akan membuat blob dari konten file dan menampilkan referensi tersembunyi ke blob, yang disebut kunci blob yang nantinya dapat digunakan untuk menyajikan blob. Aplikasi dapat menyajikan nilai blob lengkap sebagai respons terhadap permintaan pengguna, atau dapat membaca nilai secara langsung menggunakan antarmuka seperti file streaming.

Memperkenalkan Blobstore

Google App Engine mencakup layanan Blobstore, yang memungkinkan aplikasi menyajikan objek data yang hanya dibatasi oleh jumlah data yang dapat diupload atau didownload melalui satu koneksi HTTP. Objek ini disebut nilai Blobstore atau blob. Nilai Blobstore berfungsi sebagai respons dari pengendali permintaan dan dibuat sebagai file yang diupload melalui formulir web. Aplikasi tidak membuat data blob secara langsung; sebagai gantinya, blob dibuat secara tidak langsung oleh formulir web yang dikirimkan atau permintaan POST HTTP lainnya. Nilai Blobstore dapat disajikan kepada pengguna, atau diakses oleh aplikasi dalam aliran data seperti file, menggunakan Blobstore API.

Untuk meminta pengguna mengupload nilai Blobstore, aplikasi Anda harus menyajikan formulir web dengan kolom upload file. Aplikasi ini membuat URL tindakan formulir dengan memanggil Blobstore API. Browser pengguna mengupload file langsung ke Blobstore melalui URL yang dibuat. Blobstore kemudian menyimpan blob, menulis ulang permintaan untuk memuat kunci blob, dan meneruskannya ke jalur dalam aplikasi Anda. Pengendali permintaan di jalur tersebut dalam aplikasi Anda bisa melakukan pemrosesan formulir tambahan.

Untuk menyajikan blob, aplikasi Anda menetapkan header pada respons keluar, dan App Engine mengganti respons tersebut dengan nilai blob.

Blob tidak dapat diubah setelah dibuat, meskipun dapat dihapus. Setiap blob memiliki catatan info blob yang sesuai dan tersimpan di datastore, yang memberikan detail tentang blob, seperti waktu pembuatan dan jenis kontennya. Anda dapat menggunakan kunci blob untuk mengambil catatan info blob dan mengkueri propertinya.

Aplikasi dapat membaca nilai Blobstore sebagian dalam satu waktu menggunakan panggilan API. Ukuran bagian dapat mencapai ukuran maksimum dari nilai yang ditampilkan API. Ukuran ini kurang dari 32 megabyte, yang direpresentasikan di Java oleh konstanta com.google.appengine.api.blobstore.BlobstoreService.MAX_BLOB_FETCH_SIZE. Aplikasi tidak dapat membuat atau mengubah nilai Blobstore, kecuali melalui file yang diupload oleh pengguna.

Menggunakan Blobstore

Aplikasi dapat menggunakan Blobstore untuk menerima file besar sebagai upload dari pengguna dan menyajikan file tersebut. File disebut blob setelah diupload. Aplikasi tidak mengakses blob secara langsung. Sebagai gantinya, aplikasi bekerja dengan blob melalui entity info blob (diwakili oleh class BlobInfo) di datastore.

Pengguna membuat blob dengan mengirimkan formulir HTML yang menyertakan satu atau beberapa kolom input file. Aplikasi Anda menetapkan blobstoreService.createUploadUrl() sebagai tujuan (tindakan) formulir ini, dengan meneruskan fungsi jalur URL pengendali di aplikasi Anda. Saat pengguna mengirimkan formulir, browser pengguna akan mengupload file yang ditentukan langsung ke Blobstore. Blobstore menulis ulang permintaan pengguna dan menyimpan data file yang diupload, mengganti data file yang diupload dengan satu atau beberapa kunci blob yang sesuai, lalu meneruskan permintaan yang ditulis ulang ke pengendali di jalur URL yang Anda berikan ke blobstoreService.createUploadUrl(). Pengendali ini dapat melakukan pemrosesan tambahan berdasarkan kunci blob.

Aplikasi ini dapat membaca bagian dari nilai Blobstore menggunakan antarmuka streaming yang mirip file. Lihat class BlobstoreInputStream.

Mengupload blob

Untuk membuat dan mengupload blob, ikuti prosedur berikut:

1. Membuat URL upload

Panggil blobstoreService.createUploadUrl guna membuat URL upload untuk formulir yang akan diisi pengguna, yang meneruskan jalur aplikasi yang akan dimuat saat POST formulir selesai.

<body>
    <form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
        <input type="file" name="myFile">
        <input type="submit" value="Submit">
    </form>
</body>

Perhatikan bahwa ini adalah tampilan formulir upload jika dibuat sebagai JSP.

2. Membuat formulir upload

Formulir harus menyertakan kolom upload file, dan enctype formulir harus ditetapkan ke multipart/form-data. Saat pengguna mengirimkan formulir, POST akan ditangani oleh Blobstore API, yang membuat blob. API ini juga membuat catatan info untuk blob dan menyimpan catatan di datastore, dan meneruskan permintaan yang ditulis ulang ke aplikasi Anda di jalur yang diberikan sebagai kunci blob.

3. Menerapkan pengendali upload

Dalam pengendali ini, Anda dapat menyimpan kunci blob bersama model data aplikasi lainnya. Kunci blob itu sendiri tetap dapat diakses dari entity info blob di datastore. Perhatikan bahwa setelah pengguna mengirimkan formulir dan pengendali Anda dipanggil, blob telah disimpan dan info blob ditambahkan ke datastore. Jika aplikasi Anda tidak ingin menyimpan blob, Anda harus segera menghapus blob agar tidak menjadi telantar:

Dalam kode berikut, getUploads menampilkan sekumpulan blob yang telah diupload. Objek Map adalah daftar yang mengaitkan nama kolom upload dengan blob yang ada di dalamnya.

Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");

if (blobKeys == null || blobKeys.isEmpty()) {
    res.sendRedirect("/");
} else {
    res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
}

Saat Blobstore menulis ulang permintaan pengguna, bagian MIME dari file yang diupload akan dikosongkan, dan kunci blob ditambahkan sebagai header bagian MIME. Semua kolom dan bagian formulir lainnya akan dipertahankan dan diteruskan ke pengendali upload. Jika Anda tidak menentukan jenis konten, Blobstore akan mencoba menyimpulkannya dari ekstensi file. Jika tidak ada jenis konten yang dapat ditentukan, blob yang baru dibuat akan ditetapkan sebagai jenis konten application/octet-stream.

Menyajikan blob

Untuk menyajikan blob, Anda harus menyertakan pengendali download blob sebagai jalur dalam aplikasi Anda. Pengendali ini harus meneruskan kunci blob untuk blob yang diinginkan ke blobstoreService.serve(blobKey, res);. Dalam contoh ini, kunci blob diteruskan ke pengendali download sebagai argumen URL (req.getParameter('blob-key')). Dalam praktiknya, pengendali download bisa mendapatkan kunci blob dengan cara apa pun yang Anda pilih, misalnya melalui metode lain atau tindakan pengguna.

public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws IOException {
        BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
        blobstoreService.serve(blobKey, res);

Blob dapat disajikan dari URL aplikasi apa pun. Untuk menyajikan blob dalam aplikasi Anda, tempatkan header khusus dalam respons yang berisi kunci blob. App Engine mengganti isi respons dengan konten blob.

Rentang byte blob

Blobstore mendukung penyajian sebagian dari nilai yang besar, bukan nilai penuh, sebagai respons atas permintaan. Untuk menyajikan nilai parsial, sertakan header X-AppEngine-BlobRange dalam respons keluar. Nilainya adalah rentang byte HTTP standar. Penomoran byte berbasis nol. X-AppEngine-BlobRange kosong menginstruksikan API untuk mengabaikan header rentang dan menyajikan blob lengkap. Contoh rentang mencakup:

  • 0-499 menyajikan 500 byte pertama dari nilai (0 hingga 499 byte, inklusif).
  • 500-999 menyajikan 500 byte dimulai dari byte 501.
  • 500- menyajikan semua byte yang dimulai dari byte 501 hingga akhir nilai.
  • -500 menyajikan 500 byte terakhir dari nilai.

Jika rentang byte valid untuk nilai Blobstore, Blobstore akan mengirimkan kode status 206 Partial Content dan rentang byte yang diminta ke klien. Jika rentang tidak valid untuk nilai tersebut, Blobstore akan mengirim 416 Requested Range Not Satisfiable.

Blobstore tidak mendukung beberapa rentang byte dalam satu permintaan (misalnya 100-199,200-299), terlepas dari apakah keduanya tumpang-tindih atau tidak.

Menyelesaikan aplikasi contoh

Pada aplikasi contoh berikut, URL utama aplikasi memuat formulir yang meminta pengguna untuk mengupload file, dan pengendali upload segera memanggil pengendali download untuk menyajikan data. Hal ini untuk menyederhanakan aplikasi contoh. Dalam praktiknya, Anda mungkin tidak akan menggunakan URL utama untuk meminta upload data, dan Anda juga tidak akan langsung menyajikan blob yang baru saja diupload.

// file Upload.java

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;

public class Upload extends HttpServlet {
    private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {

        Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
        List<BlobKey> blobKeys = blobs.get("myFile");

        if (blobKeys == null || blobKeys.isEmpty()) {
            res.sendRedirect("/");
        } else {
            res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
        }
    }
}

// file Serve.java

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;

public class Serve extends HttpServlet {
    private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws IOException {
            BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
            blobstoreService.serve(blobKey, res);
        }
}

// file index.jsp

<%@ page import="com.google.appengine.api.blobstore.BlobstoreServiceFactory" %>
<%@ page import="com.google.appengine.api.blobstore.BlobstoreService" %>

<%
    BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
%>

<html>
    <head>
        <title>Upload Test</title>
    </head>
    <body>
        <form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
            <input type="text" name="foo">
            <input type="file" name="myFile">
            <input type="submit" value="Submit">
        </form>
    </body>
</html>

// web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

  <servlet>
    <servlet-name>Upload</servlet-name>
    <servlet-class>Upload</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>Serve</servlet-name>
    <servlet-class>Serve</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Upload</servlet-name>
    <url-pattern>/upload</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>Serve</servlet-name>
    <url-pattern>/serve</url-pattern>
  </servlet-mapping>

</web-app>

Menggunakan layanan Gambar dengan Blobstore

Layanan Gambar dapat menggunakan nilai Blobstore sebagai sumber transformasi. Ukuran gambar sumber bisa sebesar ukuran maksimum untuk nilai Blobstore. Layanan Gambar tetap menampilkan gambar yang ditransformasi ke aplikasi, sehingga ukuran gambar yang ditransformasi harus lebih kecil dari 32 megabyte. Hal ini berguna untuk membuat gambar thumbnail foto besar yang diupload oleh pengguna.

Untuk mengetahui informasi tentang penggunaan layanan Gambar dengan nilai Blobstore, lihat dokumentasi Layanan Gambar.

Menggunakan Blobstore API dengan Google Cloud Storage

Anda dapat menggunakan API Blobstore untuk menyimpan blob di Cloud Storage, bukan menyimpannya di Blobstore. Anda perlu menyiapkan bucket seperti yang dijelaskan dalam dokumentasi Google Cloud Storage dan menentukan bucket serta nama file di BlobstoreService createUploadUrl, menentukan nama bucket di parameter UploadOptions. Di pengendali upload, Anda perlu memproses metadata FileInfo yang ditampilkan dan secara eksplisit menyimpan nama file Google Cloud Storage yang diperlukan untuk mengambil blob nanti.

Anda juga dapat menyajikan objek Cloud Storage menggunakan API Blobstore.

Cuplikan kode berikut menunjukkan cara melakukannya. Contoh ini berada dalam pengendali permintaan yang mendapatkan nama bucket dan nama objek dalam permintaan. Cloud Storage membuat layanan Blobstore dan menggunakannya untuk membuat kunci blob untuk Google Cloud Storage, menggunakan nama objek dan bucket yang disediakan:

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
BlobKey blobKey = blobstoreService.createGsBlobKey(
    "/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());
blobstoreService.serve(blobKey, resp);

Kuota dan batas

Ruang yang digunakan untuk nilai Blobstore berkontribusi pada kuota Data Tersimpan (dapat ditagih). Entity info Blob di datastore diperhitungkan dalam batas terkait datastore. Perhatikan bahwa Google Cloud Storage adalah layanan bayar sesuai penggunaan; Anda akan dikenakan biaya sesuai dengan lembar harga Cloud Storage.

Untuk mengetahui informasi selengkapnya tentang kuota keamanan di seluruh sistem, lihat Kuota.

Selain kuota keamanan di seluruh sistem, batas berikut berlaku khusus untuk penggunaan Blobstore:

  • Ukuran maksimum data Blobstore yang dapat dibaca oleh aplikasi dengan satu panggilan API adalah 32 megabyte.
  • Jumlah file maksimum yang dapat diupload dalam satu format POST adalah 500.