Python 2.7은 지원이 종료되었으며 2026년 1월 31일에
지원 중단됩니다. 지원 중단 후에는 조직에서 이전에 조직 정책을 사용하여 레거시 런타임의 배포를 다시 사용 설정한 경우에도 Python 2.7 애플리케이션을 배포할 수 없습니다. 기존 Python 2.7 애플리케이션은
지원 중단 날짜 이후에도 계속 실행되고 트래픽을 수신합니다.
지원되는 최신 Python 버전으로 마이그레이션하는 것이 좋습니다.
웹 앱 Blobstore 핸들러
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
웹 앱에는 Blobstore API 작업을 위한 요청 핸들러 클래스가 포함되어 있습니다. BlobstoreUploadHandler
는 추가적인 처리를 위해 Blobstore를 통해 전달된 업로드 요청을 BlobInfo 레코드로 파싱하는 로직을 제공합니다. BlobstoreDownloadHandler
를 사용하면 어느 경로에서든 Blobstore 값을 쉽게 제공할 수 있습니다.
BlobstoreUploadHandler
값은 앱의 사용자 또는 관리자가 게시하는 파일 업로드를 통해 Blobstore에 추가됩니다. 앱은 파일 업로드 필드와 업로드를 Blobstore로 전달하는 양식 액션을 포함하여 웹 양식을 게시합니다. 앱은 함수create_upload_url()를 호출하여 양식 액션 URL을 가져오고 여기에 사용자가 파일을 업로드할 때 호출되는 앱 핸들러의 URL을 전달합니다. 웹 앱 애플리케이션은 BlobstoreUploadHandler
클래스의 서브클래스를 이 URL의 핸들러로 사용할 수 있습니다.
get_uploads()
메서드는 요청에서 업로드되는 파일마다 하나씩 할당되는 BlobInfo 객체의 목록을 반환합니다. 각 객체는 업로드되는 값의 Blobstore 키와 메타데이터(예: 파일 이름 및 크기)를 포함합니다. 업로드되는 각 파일에도 이 정보를 포함하는 상응 항목이 데이터 저장소에 있으므로 나중에 BLOB 키를 사용하여 BlobInfo 객체를 가져오거나 메타데이터 필드를 대상으로 데이터 저장소 쿼리를 수행할 수 있습니다. 업로드 핸들러는 데이터 저장소가 아닌 요청 데이터에서 이 정보를 직접 파싱합니다.
기본적으로 get_uploads()
는 요청에서 업로드되는 모든 파일에 대해 BlobInfo 객체를 반환합니다. 이 메서드는 지정된 파일 업로드 필드를 위한 파일만 가져오도록 field_name
인수도 받습니다. 반환 값은 항상 목록이며 빈 목록일 수 있습니다.
Google Cloud Storage로 BlobstoreUploadHandler
사용
Cloud Storage에서 이 업로드 핸들러를 사용하는 경우 전체 Cloud Storage 객체 파일 이름을 가져와서 저장해야 합니다. Cloud Storage에서 파일을 다시 검색할 때 이 이름이 필요하기 때문입니다.
각 업로드에 해당하는 FileInfo 레코드 목록을 반환하는 get_file_infos
함수를 사용합니다. 전체 Cloud Storage 객체 이름, 콘텐츠 유형, 생성 시간, 기타 데이터는 FileInfo
에서 확인할 수 있습니다. 자세한 내용은 링크를 참조하세요.
BlobstoreDownloadHandler
애플리케이션은 Blobstore 값을 제공하기 위해 X-AppEngine-BlobKey
헤더를 문자열 형식의 Blobstore 키 값으로 설정합니다. App Engine은 응답에서 이 헤더를 확인하고 BLOB의 값을 응답의 본문으로 제공합니다. 웹 앱 핸들러 클래스 BlobstoreDownloadHandler
를 사용하면 응답에서 이 값을 쉽게 설정할 수 있습니다.
send_blob()
메서드는 BlobKey 객체, 문자열 키, BlobInfo를 blob_key_or_info
인수로 사용하고 blob 값이 사용자에게 제공되도록 응답 데이터를 설정합니다. 이 메서드는 저장된 blob 값의 MIME 콘텐츠 유형을 재정의하는 선택적 content_type
인수를 사용합니다. 기본적으로 BLOB는 BLOB를 업로드한 클라이언트가 설정한 콘텐츠 유형, 파일 이름에서 파생된 콘텐츠 유형, 다른 유형 정보가 없는 경우 일반적인 유형으로 제공됩니다.
send_blob()
메서드는 blob 데이터가 원시 응답 데이터로 전송되는지 아니면 파일 이름이 지정된 MIME 첨부파일로 전송되는지 여부를 결정하는 save_as
인수를 허용합니다. 인수가 문자열이면 blob이 첨부파일로 전송되고 문자열 값이 파일 이름으로 사용됩니다. True
이고 blob_key_or_info
가 BlobInfo
객체인 경우 객체의 파일 이름이 사용됩니다. 기본적으로 BLOB 데이터는 MIME 첨부파일이 아닌 응답의 본문으로 전송됩니다.
Blobstore는 바이트 색인의 범위로 설명되는 전체 값 대신 값의 일부만 보내는 작업을 지원합니다. 두 가지 방법으로 BlobstoreDownloadHandler
의 send_blob()
메서드에 바이트 색인 범위를 제공할 수 있습니다. 첫 번째는 범위를 start
및 end
인수로 지정하는 것입니다.
# Send the first 1,000 bytes of the value.
self.send_blob(key, start=0, end=999)
기본적으로 BlobstoreDownloadHandler
는 요청의 range
헤더를 준수합니다. 원본 범위 헤더를 사용하지 못하도록 차단하려면 use_range=False
매개변수를 send_blob()
에 제공합니다.
# Send the full value of the blob and
# block the "range" header.
self.send_blob(key, use_range=False)
range
헤더의 값은 표준 HTTP 바이트 범위입니다. BlobstoreDownloadHandler
는 webob.byterange를 사용하여 이 헤더 값을 파싱합니다.
전체 샘플 애플리케이션
다음 샘플 애플리케이션에서는 애플리케이션의 기본 URL이 사용자에게 업로드할 파일을 요청하는 양식을 로드합니다. 그런 다음 업로드 핸들러가 즉시 다운로드 핸들러를 호출하여 데이터를 제공합니다. 이는 샘플 애플리케이션을 단순화하기 위한 것입니다. 실제로는 기본 URL을 사용하여 업로드 데이터를 요청하거나 방금 업로드한 BLOB를 즉시 제공하지 않을 가능성이 높습니다.
달리 명시되지 않는 한 이 페이지의 콘텐츠에는 Creative Commons Attribution 4.0 라이선스에 따라 라이선스가 부여되며, 코드 샘플에는 Apache 2.0 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 Google Developers 사이트 정책을 참조하세요. 자바는 Oracle 및/또는 Oracle 계열사의 등록 상표입니다.
최종 업데이트: 2025-09-04(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-04(UTC)"],[[["\u003cp\u003e\u003ccode\u003eBlobstoreUploadHandler\u003c/code\u003e is used to manage file uploads to the Blobstore, parsing upload requests and providing \u003ccode\u003eBlobInfo\u003c/code\u003e objects containing data about each file.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003eget_uploads()\u003c/code\u003e method retrieves a list of \u003ccode\u003eBlobInfo\u003c/code\u003e objects for uploaded files, offering options to filter by specific file upload fields.\u003c/p\u003e\n"],["\u003cp\u003eWhen using \u003ccode\u003eBlobstoreUploadHandler\u003c/code\u003e with Google Cloud Storage, \u003ccode\u003eget_file_infos\u003c/code\u003e should be used to get a \u003ccode\u003eFileInfo\u003c/code\u003e record, in order to obtain the full cloud storage object name.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003eBlobstoreDownloadHandler\u003c/code\u003e facilitates serving Blobstore values by setting the \u003ccode\u003eX-AppEngine-BlobKey\u003c/code\u003e header, allowing you to serve blobs directly to users from a specific path.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003esend_blob()\u003c/code\u003e method in \u003ccode\u003eBlobstoreDownloadHandler\u003c/code\u003e provides options to serve blobs as raw data or as a MIME attachment with a filename, and supports sending partial blob data via byte ranges.\u003c/p\u003e\n"]]],[],null,["# webapp Blobstore Handlers\n\nwebapp includes request handler classes for working with the\n[Blobstore API](/appengine/docs/legacy/standard/python/blobstore). `BlobstoreUploadHandler`\nprovides logic for parsing the upload request passed via the Blobstore into\n[BlobInfo](/appengine/docs/legacy/standard/python/refdocs/google.appengine.ext.blobstore.blobstore#google.appengine.ext.blobstore.blobstore.BlobInfo)\nrecords for further processing. `BlobstoreDownloadHandler` makes it easy to serve\nBlobstore values from any path.\n\nBlobstoreUploadHandler\n----------------------\n\nValues are added to the Blobstore via file uploads posted by users or administrators of the app.\nThe app posts a web form with a file upload field and a form action that directs the upload to the\nBlobstore. The app gets the form action URL by calling a function\n([create_upload_url()](/appengine/docs/legacy/standard/python/refdocs/google.appengine.ext.blobstore.blobstore#google.appengine.ext.blobstore.blobstore.create_upload_url)),\npassing it the URL of an app handler that gets called when users upload files. A webapp\napplication can use a subclass of the `BlobstoreUploadHandler` class as the handler for\nthis URL.\n\nThe `get_uploads()` method returns a list of\n[BlobInfo](/appengine/docs/legacy/standard/python/refdocs/google.appengine.ext.blobstore.blobstore#google.appengine.ext.blobstore.blobstore.BlobInfo)\nobjects, one for each uploaded file in the request. Each object contains the Blobstore key for\nthe uploaded value, as well as metadata such as the filename and size. Each uploaded file also\nhas a corresponding entity in the datastore with this information, so you can fetch the BlobInfo\nobject later given a blob key, or perform a datastore query over the metadata fields. The upload\nhandler parses this information directly from the request data, not the datastore.\n\nBy default, `get_uploads()` returns BlobInfo objects for all uploaded files in the\nrequest. The method also accepts a `field_name` argument to get just the file (or\nfiles) for a given file upload field. The return value is always a list, possibly an empty list. \n\n class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):\n def post(self):\n upload = self.get_uploads()[0]\n user_photo = UserPhoto(\n user=users.get_current_user().user_id(),\n blob_key=upload.key())\n user_photo.put()\n\n self.redirect('/view_photo/%s' % upload.key())\n\n### Using `BlobstoreUploadHandler` with Google Cloud Storage\n\nIf you use this upload handler with Cloud Storage, you'll need to get and store the full\nCloud Storage object file name, since this is required to retrieve the file again from Cloud Storage.\nUse the function `get_file_infos`, which returns a list of\n[FileInfo](/appengine/docs/legacy/standard/python/refdocs/google.appengine.ext.blobstore.blobstore#google.appengine.ext.blobstore.blobstore.FileInfo) records\ncorresponding to each upload. The full Cloud Storage object name, content type, creation\ntime, and other data are available in the `FileInfo`. (See the link for complete details.)\n\nBlobstoreDownloadHandler\n------------------------\n\nTo serve a Blobstore value, the application sets the `X-AppEngine-BlobKey` header to\nthe value of a Blobstore key, in string form. When App Engine sees this header in the response,\nit serves the value of the blob as the body of the response. The webapp handler class\n`BlobstoreDownloadHandler` makes it easy to set this value in the response.\n\nThe `send_blob()` method takes a\n[BlobKey](/appengine/docs/legacy/standard/python/refdocs/google.appengine.ext.blobstore.blobstore#google.appengine.ext.blobstore.blobstore.BlobKey)\nobject, a string key, or a\n[BlobInfo](/appengine/docs/legacy/standard/python/refdocs/google.appengine.ext.blobstore.blobstore#google.appengine.ext.blobstore.blobstore.BlobInfo)\nas the `blob_key_or_info` argument, and sets the response data so that the blob value\nwill be served to the user. The method takes an optional `content_type` argument which\noverrides the MIME content type of the stored blob value. By default, the blob is served with the\ncontent type set by the client that uploaded it, a content type derived from the filename, or a\ngeneric type if no other type information is available.\n\nThe `send_blob()` method accepts a `save_as` argument that determines\nwhether the blob data is sent as raw response data or as a MIME attachment with a filename. If\nthe argument is a string, the blob is sent as an attachment, and the string value is used as\nthe filename. If `True` and `blob_key_or_info` is a `BlobInfo`\nobject, the filename from the object is used. By default, the blob data is sent as the body of\nthe response and not as a MIME attachment. \n\n class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):\n def get(self, photo_key):\n if not blobstore.get(photo_key):\n self.error(404)\n else:\n self.send_blob(photo_key)\n\nThe Blobstore supports sending just part of a value instead of the full value, described as a range of byte indexes. You can provide a byte index range to `BlobstoreDownloadHandler`'s `send_blob()` method in two ways. The first is to specify the range as the arguments `start` and `end`: \n\n```python\n # Send the first 1,000 bytes of the value.\n self.send_blob(key, start=0, end=999)\n```\n\nBy default, the `BlobstoreDownloadHandler` honors the `range` header in the request. If you wish to block use of the original range header, provide the parameter `use_range=False` to `send_blob()`: \n\n```python\n # Send the full value of the blob and\n # block the \"range\" header.\n self.send_blob(key, use_range=False)\n```\n\nThe value of the `range` header is a standard [HTTP byte range](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). `BlobstoreDownloadHandler` uses [webob.byterange](http://pythonpaste.org/webob/modules/webob.html) to parse this header value.\n\nComplete sample application\n---------------------------\n\nIn the following sample application, the application's main URL loads the form that asks the user\nfor a file to upload, and the upload handler immediately calls the download handler to serve the\ndata. This is to simplify the sample application. In practice, you would probably not use the main\nURL to request upload data, nor would you immediately serve a blob you had just uploaded. \n\n from google.appengine.api import users\n from google.appengine.ext import blobstore\n from google.appengine.ext import ndb\n from google.appengine.ext.webapp import blobstore_handlers\n import webapp2\n\n\n # This datastore model keeps track of which users uploaded which photos.\n class UserPhoto(ndb.Model):\n user = ndb.StringProperty()\n blob_key = ndb.BlobKeyProperty()\n\n\n class PhotoUploadFormHandler(webapp2.RequestHandler):\n def get(self):\n upload_url = blobstore.create_upload_url('/upload_photo')\n # To upload files to the blobstore, the request method must be \"POST\"\n # and enctype must be set to \"multipart/form-data\".\n self.response.out.write(\"\"\"\n \u003chtml\u003e\u003cbody\u003e\n \u003cform action=\"{0}\" method=\"POST\" enctype=\"multipart/form-data\"\u003e\n Upload File: \u003cinput type=\"file\" name=\"file\"\u003e\u003cbr\u003e\n \u003cinput type=\"submit\" name=\"submit\" value=\"Submit\"\u003e\n \u003c/form\u003e\n \u003c/body\u003e\u003c/html\u003e\"\"\".format(upload_url))\n\n\n class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler):\n def post(self):\n upload = self.get_uploads()[0]\n user_photo = UserPhoto(\n user=users.get_current_user().user_id(),\n blob_key=upload.key())\n user_photo.put()\n\n self.redirect('/view_photo/%s' % upload.key())\n\n\n class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):\n def get(self, photo_key):\n if not blobstore.get(photo_key):\n self.error(404)\n else:\n self.send_blob(photo_key)\n\n\n app = webapp2.WSGIApplication([\n ('/', PhotoUploadFormHandler),\n ('/upload_photo', PhotoUploadHandler),\n ('/view_photo/([^/]+)?', ViewPhotoHandler),\n ], debug=True)"]]