סקירה כללית על Blobstore API לשירותים בחבילה מדור קודם

ממשק ה-API של Blobstore מאפשר לאפליקציה שלכם להציג אובייקטים של נתונים, שנקראים blobs,שהגודל שלהם גדול בהרבה מהגודל המקסימלי של אובייקטים בשירות Datastore. ‫Blob שימושי להצגת קבצים גדולים, כמו קובצי וידאו או תמונות, ולאפשר למשתמשים להעלות קבצים גדולים של נתונים. ‫Blobs נוצרים על ידי העלאת קובץ באמצעות בקשת HTTP. בדרך כלל, האפליקציות עושות את זה על ידי הצגת טופס עם שדה להעלאת קובץ למשתמש. כששולחים את הטופס, Blobstore יוצר blob מתוכן הקובץ ומחזיר הפניה אטומה ל-blob, שנקראת מפתח blob,שאפשר להשתמש בה בהמשך כדי להציג את ה-blob. האפליקציה יכולה להציג את הערך המלא של ה-blob בתגובה לבקשת משתמש, או לקרוא את הערך ישירות באמצעות ממשק דמוי קובץ של סטרימינג.

חדש: Blobstore

‫App Engine כולל את שירות Blobstore, שמאפשר לאפליקציות להציג אובייקטים של נתונים שמוגבלים רק בכמות הנתונים שאפשר להעלות או להוריד דרך חיבור HTTP יחיד. האובייקטים האלה נקראים ערכי Blobstore או blobs. ערכים של Blobstore מוגשים כתשובות מ-handlers של בקשות, והם נוצרים כהעלאות דרך טפסים באינטרנט. אפליקציות לא יוצרות נתוני Blob ישירות. במקום זאת, הן יוצרות Blob באופן עקיף, באמצעות טופס אינטרנט שנשלח או בקשת HTTP POST אחרת. אפשר להציג למשתמש ערכים של Blobstore או לגשת אליהם באמצעות האפליקציה בזרם דמוי קובץ, באמצעות Blobstore API.

כדי לבקש ממשתמש להעלות ערך Blobstore, האפליקציה מציגה טופס אינטרנטי עם שדה להעלאת קובץ. האפליקציה יוצרת את כתובת ה-URL של הפעולה בטופס על ידי קריאה ל-Blobstore API. הדפדפן של המשתמש מעלה את הקובץ ישירות אל מאגר ה-Blob באמצעות כתובת ה-URL שנוצרה. לאחר מכן, Blobstore מאחסן את ה-blob, כותב מחדש את הבקשה כך שתכיל את מפתח ה-blob ומעביר אותה לנתיב באפליקציה. ה-request handler בנתיב הזה באפליקציה יכול לבצע עיבוד נוסף של הטופס.

כדי להציג blob, האפליקציה מגדירה כותרת בתגובה היוצאת, ו-App Engine מחליף את התגובה בערך ה-blob.

אי אפשר לשנות את ה-blob אחרי שיוצרים אותו, אבל אפשר למחוק אותו. לכל blob יש רשומה של פרטי ה-blob תואמת, שמאוחסנת במאגר הנתונים ומספקת פרטים על ה-blob, כמו זמן היצירה וסוג התוכן. אפשר להשתמש במפתח ה-blob כדי לאחזר רשומות של פרטי blob ולשאול על המאפיינים שלהן.

אפליקציה יכולה לקרוא ערך של Blobstore חלק אחרי חלק באמצעות קריאה ל-API. גודל החלק יכול להיות עד הגודל המקסימלי של ערך מוחזר של API. הגודל הזה קטן קצת מ-32 מגה-בייט, והוא מיוצג ב-Python על ידי הקבוע google.appengine.ext.blobstore.MAX_BLOB_FETCH_SIZE . אפליקציה לא יכולה ליצור או לשנות ערכים ב-Blobstore, אלא רק באמצעות קבצים שהמשתמש העלה.

שימוש ב-Blobstore

אפליקציות יכולות להשתמש ב-Blobstore כדי לקבל קבצים גדולים כהעלאות ממשתמשים וכדי להציג את הקבצים האלה. אחרי שהקבצים מועלים, הם נקראים blobs. אפליקציות לא ניגשות ל-blobs ישירותבמקום זאת, האפליקציות עובדות עם blobs דרך יחידות מידע של blob (שמיוצגות על ידי המחלקה BlobInfo ) ב-Datastore.

המשתמש יוצר blob על ידי שליחת טופס HTML שכולל שדה קלט אחד או יותר של קובץ. האפליקציה שלך calls blobstore.create_upload_url() כדי לקבל את היעד (הפעולה) של הטופס הזה, ולהעביר לפונקציה נתיב כתובת ה-URL של handler באפליקציה שלך. כשהמשתמש שולח את הטופס, הדפדפן של המשתמש מעלה את הקבצים שצוינו ישירות אל Blobstore. שירות Blobstore כותב מחדש את הבקשה של המשתמש ומאחסן את נתוני הקובץ שהועלה, מחליף את נתוני הקובץ שהועלה במפתח blob אחד או יותר, ואז מעביר את הבקשה שנכתבה מחדש ל-handler בנתיב כתובת ה-URL שסיפקתם ל- blobstore.create_upload_url() .

ה-handler הזה יכול לבצע עיבוד נוסף על סמך מפתח ה-blob.

האפליקציה יכולה לקרוא חלקים מערך Blobstore באמצעות ממשק סטרימינג דמוי קובץ. אפשר לעיין בכיתה BlobReader.

העלאת blob

כדי ליצור ולהעלות blob, פועלים לפי השלבים הבאים:

1. יצירת כתובת URL להעלאה

מפעילים את blobstore.create_upload_url() כדי ליצור כתובת URL להעלאה של הטופס שהמשתמש ימלא, ומעבירים את נתיב האפליקציה לטעינה כשמילוי הטופס POST מסתיים.

upload_url = blobstore.create_upload_url("/upload_photo")

יש גרסה אסינכרונית, create_upload_url_async(). היא מאפשרת לקוד האפליקציה להמשיך לפעול בזמן ש-Blobstore יוצר את כתובת ה-URL להעלאה.

2. יצירת טופס להעלאה

הטופס חייב לכלול שדה להעלאת קובץ, והערך של enctype בטופס צריך להיות multipart/form-data. כשהמשתמש שולח את הטופס, ה-POST מטופל על ידי Blobstore API, שיוצר את ה-blob. בנוסף, ה-API יוצר רשומת מידע עבור ה-blob, מאחסן את הרשומה ב-Datastore ומעביר את הבקשה שנכתבה מחדש לאפליקציה בנתיב הנתון כמפתח blob.

צריך להציג את הדף של הטופס עם Content-Type של text/html; charset=utf-8, אחרת המערכת תפרש באופן שגוי שמות קבצים עם תווים שהם לא ASCII.
מכיוון ש-Blobstore ל-Python 3 לא משתמש ב-webapp, צריך להגדיר Content-Type משלכם כדי למנוע ממסגרת האינטרנט להגדיר סוג תוכן שמוגדר כברירת מחדל, ומ-App Engine להגדיר סוג משוער.

אי אפשר להשתמש במאזן עומסים חיצוני גלובלי של אפליקציות עם Serverless NEG כדי לטפל בבקשות העלאה שנשלחות לכתובת ה-URL‏ /_ah/upload/ שמוחזרת מהקריאה blobstore.create_upload_url. במקום זאת, צריך לנתב את בקשות ההעלאה האלה ישירות לשירות App Engine. אפשר לעשות זאת באמצעות הדומיין appspot.com או דומיין מותאם אישית שממופה ישירות לשירות App Engine.

3. הטמעה של handler להעלאה

ב-handler הזה, אפשר לאחסן את מפתח ה-blob עם שאר נתוני מודל הנתונים של האפליקציה. מפתח ה-blob עצמו נשאר נגיש מהישות של פרטי ה-blob ב-Datastore. שימו לב: אחרי שהמשתמש שולח את הטופס והפונקציה לטיפול בבקשות נקראת, ה-blob כבר נשמר ופרטי ה-blob נוספו ל-Datastore. אם האפליקציה לא רוצה לשמור את ה-blob, צריך למחוק אותו באופן מיידי כדי למנוע מצב שבו הוא הופך ל-blob יתום.

בכל אפליקציות Flask, כל הקריאות לשיטות במחלקה BlobstoreUploadHandler מחייבות את request.environ dictionary (הבקשה מיובאת ממודול Flask). אם האפליקציה שלכם היא אפליקציית WSGI בלי מסגרת אינטרנט, אתם משתמשים בפרמטר environ בשיטה get_uploads(). כשכותבים מחדש את בקשת המשתמש, Blobstore מרוקן את חלקי ה-MIME של הקבצים שהועלו ומוסיף את מפתח ה-blob ככותרת של חלק ה-MIME. ‫Blobstore שומר את כל שאר השדות והחלקים בטופס ומעביר אותם ל-upload handler. אם לא מציינים סוג תוכן, Blobstore ינסה להסיק אותו מהסיומת של הקובץ. אם לא ניתן לקבוע את סוג התוכן, סוג התוכן application/octet-stream מוקצה ל-blob שנוצר.

הצגת אובייקט blob

כדי להציג blob, צריך לכלול באפליקציה נתיב של handler להורדת blob. האפליקציה מציגה blob על ידי הגדרת כותרת בתגובה היוצאת. אם משתמשים ב-Flask, המחלקה BlobstoreDownloadHandler דורשת את המילון request.environ (הבקשה מיובאת ממודול Flask). אם האפליקציה היא אפליקציית WSGI ללא מסגרת אינטרנט, משתמשים בפרמטר environ בשיטות send_blob()

אפשר להציג Blob מכל כתובת URL של אפליקציה. כדי להציג blob באפליקציה, צריך להוסיף כותרת מיוחדת לתשובה שמכילה את מפתח ה-blob. ‫App Engine מחליף את תוכן התגובה בתוכן ה-blob.

טווחי בייטים של Blob

‫Blobstore תומך בהצגת חלק מערך גדול במקום הערך המלא בתגובה לבקשה. כדי להציג ערך חלקי, צריך לכלול את הכותרת X-AppEngine-BlobRange בתשובה היוצאת. הערך שלו הוא טווח בייטים ב-HTTP סטנדרטי. מספור הבייטים מבוסס על אפסים. אם משאירים את X-AppEngine-BlobRange ריק, ה-API מתעלם מכותרת הטווח ומציג את ה-blob המלא. דוגמאות לטווחים:

  • 0-499 מציג את 500 הבייטים הראשונים של הערך (בייטים 0 עד 499, כולל).
  • 500-999 מחזירה 500 בייטים החל מהבייט ה-501.
  • 500- מציג את כל הבייטים החל מהבייט ה-501 ועד לסוף הערך.
  • -500 מציג את 500 הבייטים האחרונים של הערך.

אם טווח הבייטים תקין לערך Blobstore, ‏ Blobstore שולח ללקוח את קוד הסטטוס 206 Partial Content ואת טווח הבייטים המבוקש. אם הטווח לא תקף עבור הערך, Blobstore שולח 416 Requested Range Not Satisfiable.

‫Blobstore לא תומך בטווחים מרובים של בייטים בבקשה אחת (לדוגמה, 100-199,200-299), בין אם יש חפיפה ביניהם ובין אם לא.

השלמת בקשה לדוגמה

אפשר לראות דוגמה לאפליקציית Flask במדריך Blobstore API for Python 3.

שימוש בשירות Images עם Blobstore

שירות התמונות יכול להשתמש בערך Blobstore כמקור לטרנספורמציה. גודל תמונת המקור יכול להיות עד הגודל המקסימלי של ערך Blobstore. שירות התמונות עדיין מחזיר את התמונה שעברה שינוי לאפליקציה, ולכן הגודל של התמונה שעברה שינוי צריך להיות קטן מ-32 מגה-בייט. האפשרות הזו שימושית ליצירת תמונות ממוזערות של תמונות גדולות שהועלו על ידי משתמשים. מידע על השימוש בשירות התמונות עם ערכי Blobstore זמין ב מסמכי התיעוד של Images Service

שימוש ב-Blobstore API עם Cloud Storage

אתם יכולים להשתמש ב-Blobstore API כדי לאחסן blobs ב-Cloud Storage במקום לאחסן אותם ב-Blobstore. צריך להגדיר קטגוריה כמו שמתואר במסמכי התיעוד של Cloud Storage, לציין את הקטגוריה ואת שם הקובץ ב- פרמטר blobstore.create_upload_url gs_bucket_name.

ב-upload handler, צריך לעבד את המטא-נתונים של המטא-נתונים של FileInfo ולשמור באופן מפורש את שם הקובץ ב-Cloud Storage שנדרש כדי לאחזר את ה-blob מאוחר יותר.

אפשר גם להציג אובייקטים ב-Cloud Storage באמצעות Blobstore API.

אם אתם רוצים פתרון אחסון אובייקטים מודרני יותר, כדאי לשקול מעבר מ-Blobstore של App Engine ל-Cloud Storage.

שימוש ב-BlobReader

אפליקציה יכולה לקרוא נתונים מערכים של Blobstore באמצעות ממשק שדומה לאובייקט file של Python. הממשק הזה יכול להתחיל לקרוא ערך בכל מיקום של בייט, והוא משתמש בכמה קריאות לשירות ובאגירה בזיכרון, כך שאפליקציה יכולה לגשת לגודל המלא של הערך למרות המגבלה על הגודל של תגובה יחידה לקריאה לשירות.

הארגומנט של הקונסטרוקטור של המחלקה BlobReader יכול להיות אחד משלושת הערכים הבאים:

האובייקט מיישם את שיטות הקובץ המוכרות לקריאת הערך. האפליקציה לא יכולה לשנות את הערך של Blobstore. שיטות הקבצים לכתיבה לא מיושמות.

# Instantiate a BlobReader for a given Blobstore blob_key.
blob_reader = blobstore.BlobReader(blob_key)

# Instantiate a BlobReader for a given Blobstore blob_key, setting the
# buffer size to 1 MB.
blob_reader = blobstore.BlobReader(blob_key, buffer_size=1048576)

# Instantiate a BlobReader for a given Blobstore blob_key, setting the
# initial read position.
blob_reader = blobstore.BlobReader(blob_key, position=0)

# Read the entire value into memory. This may take a while depending
# on the size of the value and the size of the read buffer, and is not
# recommended for large values.
blob_reader_data = blob_reader.read()

# Write the contents to the response.
self.response.headers["Content-Type"] = "text/plain"
self.response.write(blob_reader_data)

# Set the read position back to 0, then read and write 3 bytes.
blob_reader.seek(0)
blob_reader_data = blob_reader.read(3)
self.response.write(blob_reader_data)
self.response.write("\n")

# Set the read position back to 0, then read and write one line (up to
# and including a '\n' character) at a time.
blob_reader.seek(0)
for line in blob_reader:
    self.response.write(line)

שליחת בקשות אסינכרוניות

אפליקציה יכולה לקרוא לפונקציות מסוימות של Blobstore שפועלות ברקע. ‫Blobstore מבצע את הבקשה בזמן שהאפליקציה עושה דברים אחרים. כדי לשלוח את הבקשה, האפליקציה קוראת לפונקציה לא סינכרונית. הפונקציה מחזירה מיד אובייקט RPC שמייצג את הבקשה. כשהאפליקציה צריכה את התוצאה של הבקשה, היא קוראת לשיטה get_result() של אובייקט ה-RPC.

אם השירות לא השלים את הבקשה כשהאפליקציה קוראת ל-get_result(), השיטה ממתינה עד שהבקשה תושלם (או עד שהגיע המועד האחרון, או עד שמתרחשת שגיאה). השיטה מחזירה את אובייקט התוצאה, או מעלה חריגה אם קרתה שגיאה במהלך ביצוע הבקשה. לדוגמה, קטע הקוד הזה

upload_url = blobstore.create_upload_url('/upload')
slow_operation()
self.response.out.write("""<form action="%s" method="POST"
                           enctype="multipart/form-data">""" % upload_url)

הופך ל-

upload_url_rpc = blobstore.create_upload_url_async('/upload')
slow_operation()
upload_url = upload_url_rpc.get_result()
self.response.out.write("""<form action="%s" method="POST"
                           enctype="multipart/form-data">""" % upload_url)

בדוגמה הזו, האפליקציה מבצעת את הקוד slow_operation() באותו הזמן ש-Blobstore יוצר את כתובת ה-URL להעלאה.

מכסות ומגבלות

הנפח שמשמש לאחסון ערכים ב-Blobstore נכלל במכסת Stored Data (billable). יחידות מידע מסוג Blob ב-Datastore נספרות במסגרת המגבלות שקשורות ל-Datastore. שימו לב ש-Cloud Storage הוא שירות בתשלום, ותחויבו בהתאם למחירון של Cloud Storage.

מידע נוסף על מכסות בטיחות בכל המערכת זמין במאמר בנושא מכסות.

בנוסף למכסות הבטיחות שחלות על כל המערכת, המגבלות הבאות חלות באופן ספציפי על השימוש ב-Blobstore:

  • הגודל המקסימלי של נתונים ב-Blobstore שאפשר לקרוא באמצעות האפליקציה בקריאת API אחת הוא 32 מגה-בייט.
  • המספר המקסימלי של קבצים שאפשר להעלות בטופס POST יחיד הוא 500.