Skip to content

Commit 9da144a

Browse files
ryanmatsJon Wayne Parrott
authored and
Jon Wayne Parrott
committed
Blobstore API with Google Cloud Storage samples (#709)
1 parent e047afa commit 9da144a

14 files changed

+258
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
runtime: python27
2+
api_version: 1
3+
threadsafe: yes
4+
5+
handlers:
6+
- url: .*
7+
script: main.app
8+
login: required
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2016 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.appengine.ext import vendor
16+
17+
# Add any libraries installed in the "lib" folder.
18+
vendor.add('lib')
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""A sample app that operates on GCS files with blobstore API's BlobReader."""
2+
3+
import cloudstorage
4+
from google.appengine.api import app_identity
5+
from google.appengine.ext import blobstore
6+
import webapp2
7+
8+
9+
class BlobreaderHandler(webapp2.RequestHandler):
10+
def get(self):
11+
# Get the default Cloud Storage Bucket name and create a file name for
12+
# the object in Cloud Storage.
13+
bucket = app_identity.get_default_gcs_bucket_name()
14+
15+
# Cloud Storage file names are in the format /bucket/object.
16+
filename = '/{}/blobreader_demo'.format(bucket)
17+
18+
# Create a file in Google Cloud Storage and write something to it.
19+
with cloudstorage.open(filename, 'w') as filehandle:
20+
filehandle.write('abcde\n')
21+
22+
# In order to read the contents of the file using the Blobstore API,
23+
# you must create a blob_key from the Cloud Storage file name.
24+
# Blobstore expects the filename to be in the format of:
25+
# /gs/bucket/object
26+
blobstore_filename = '/gs{}'.format(filename)
27+
blob_key = blobstore.create_gs_key(blobstore_filename)
28+
29+
# [START blob_reader]
30+
# Instantiate a BlobReader for a given Blobstore blob_key.
31+
blob_reader = blobstore.BlobReader(blob_key)
32+
33+
# Instantiate a BlobReader for a given Blobstore blob_key, setting the
34+
# buffer size to 1 MB.
35+
blob_reader = blobstore.BlobReader(blob_key, buffer_size=1048576)
36+
37+
# Instantiate a BlobReader for a given Blobstore blob_key, setting the
38+
# initial read position.
39+
blob_reader = blobstore.BlobReader(blob_key, position=0)
40+
41+
# Read the entire value into memory. This may take a while depending
42+
# on the size of the value and the size of the read buffer, and is not
43+
# recommended for large values.
44+
blob_reader_data = blob_reader.read()
45+
46+
# Write the contents to the response.
47+
self.response.headers['Content-Type'] = 'text/plain'
48+
self.response.write(blob_reader_data)
49+
50+
# Set the read position back to 0, then read and write 3 bytes.
51+
blob_reader.seek(0)
52+
blob_reader_data = blob_reader.read(3)
53+
self.response.write(blob_reader_data)
54+
self.response.write('\n')
55+
56+
# Set the read position back to 0, then read and write one line (up to
57+
# and including a '\n' character) at a time.
58+
blob_reader.seek(0)
59+
for line in blob_reader:
60+
self.response.write(line)
61+
# [END blob_reader]
62+
63+
# Delete the file from Google Cloud Storage using the blob_key.
64+
blobstore.delete(blob_key)
65+
66+
67+
app = webapp2.WSGIApplication([
68+
('/', BlobreaderHandler),
69+
('/blobreader', BlobreaderHandler)], debug=True)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import webtest
16+
17+
import main
18+
19+
20+
def test_blobreader(testbed, login):
21+
app = webtest.TestApp(main.app)
22+
23+
response = app.get('/blobreader')
24+
25+
assert 'abcde\nabc\nabcde\n' in response
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GoogleAppEngineCloudStorageClient==1.9.22.1
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
runtime: python27
2+
api_version: 1
3+
threadsafe: yes
4+
5+
handlers:
6+
- url: .*
7+
script: main.app
8+
login: required
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2016 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.appengine.ext import vendor
16+
17+
# Add any libraries installed in the "lib" folder.
18+
vendor.add('lib')
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""A sample app that operates on GCS files with blobstore API."""
2+
3+
import cloudstorage
4+
from google.appengine.api import app_identity
5+
from google.appengine.ext import blobstore
6+
from google.appengine.ext.webapp import blobstore_handlers
7+
import webapp2
8+
9+
10+
# This handler creates a file in Cloud Storage using the cloudstorage
11+
# client library and then reads the data back using the Blobstore API.
12+
class CreateAndReadFileHandler(webapp2.RequestHandler):
13+
def get(self):
14+
# Get the default Cloud Storage Bucket name and create a file name for
15+
# the object in Cloud Storage.
16+
bucket = app_identity.get_default_gcs_bucket_name()
17+
18+
# Cloud Storage file names are in the format /bucket/object.
19+
filename = '/{}/blobstore_demo'.format(bucket)
20+
21+
# Create a file in Google Cloud Storage and write something to it.
22+
with cloudstorage.open(filename, 'w') as filehandle:
23+
filehandle.write('abcde\n')
24+
25+
# In order to read the contents of the file using the Blobstore API,
26+
# you must create a blob_key from the Cloud Storage file name.
27+
# Blobstore expects the filename to be in the format of:
28+
# /gs/bucket/object
29+
blobstore_filename = '/gs{}'.format(filename)
30+
blob_key = blobstore.create_gs_key(blobstore_filename)
31+
32+
# Read the file's contents using the Blobstore API.
33+
# The last two parameters specify the start and end index of bytes we
34+
# want to read.
35+
data = blobstore.fetch_data(blob_key, 0, 6)
36+
37+
# Write the contents to the response.
38+
self.response.headers['Content-Type'] = 'text/plain'
39+
self.response.write(data)
40+
41+
# Delete the file from Google Cloud Storage using the blob_key.
42+
blobstore.delete(blob_key)
43+
44+
45+
# This handler creates a file in Cloud Storage using the cloudstorage
46+
# client library and then serves the file back using the Blobstore API.
47+
class CreateAndServeFileHandler(blobstore_handlers.BlobstoreDownloadHandler):
48+
49+
def get(self):
50+
# Get the default Cloud Storage Bucket name and create a file name for
51+
# the object in Cloud Storage.
52+
bucket = app_identity.get_default_gcs_bucket_name()
53+
54+
# Cloud Storage file names are in the format /bucket/object.
55+
filename = '/{}/blobstore_serving_demo'.format(bucket)
56+
57+
# Create a file in Google Cloud Storage and write something to it.
58+
with cloudstorage.open(filename, 'w') as filehandle:
59+
filehandle.write('abcde\n')
60+
61+
# In order to read the contents of the file using the Blobstore API,
62+
# you must create a blob_key from the Cloud Storage file name.
63+
# Blobstore expects the filename to be in the format of:
64+
# /gs/bucket/object
65+
blobstore_filename = '/gs{}'.format(filename)
66+
blob_key = blobstore.create_gs_key(blobstore_filename)
67+
68+
# BlobstoreDownloadHandler serves the file from Google Cloud Storage to
69+
# your computer using blob_key.
70+
self.send_blob(blob_key)
71+
72+
73+
app = webapp2.WSGIApplication([
74+
('/', CreateAndReadFileHandler),
75+
('/blobstore/read', CreateAndReadFileHandler),
76+
('/blobstore/serve', CreateAndServeFileHandler)], debug=True)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import webtest
16+
17+
import main
18+
19+
20+
def test_create_and_read(testbed, login):
21+
app = webtest.TestApp(main.app)
22+
23+
response = app.get('/blobstore/read')
24+
25+
assert 'abcde' in response
26+
27+
28+
def test_create_and_serve(testbed, login):
29+
app = webtest.TestApp(main.app)
30+
31+
response = app.get('/blobstore/serve')
32+
served_file_header = response.headers['X-AppEngine-BlobKey']
33+
34+
assert 'encoded_gs_file' in served_file_header
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GoogleAppEngineCloudStorageClient==1.9.22.1

0 commit comments

Comments
 (0)