Skip to content

Commit 6454cf0

Browse files
committed
Merge pull request #217 from GoogleCloudPlatform/upload-object
Add sample for CRUD on GCS.
2 parents 56c0651 + d16f704 commit 6454cf0

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

storage/api/crud_object.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright (C) 2016 Google Inc.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
"""Application for uploading an object using the Cloud Storage API.
18+
19+
This sample is used on this page:
20+
21+
https://cloud.google.com/storage/docs/json_api/v1/json-api-python-samples
22+
23+
For more information, see the README.md under /storage.
24+
"""
25+
26+
import argparse
27+
import filecmp
28+
import json
29+
import tempfile
30+
31+
from googleapiclient import discovery
32+
from googleapiclient import http
33+
34+
from oauth2client.client import GoogleCredentials
35+
36+
37+
def main(bucket, filename, readers=[], owners=[]):
38+
print('Uploading object..')
39+
resp = upload_object(bucket, filename, readers, owners)
40+
print(json.dumps(resp, indent=2))
41+
42+
print('Fetching object..')
43+
with tempfile.NamedTemporaryFile(mode='w+b') as tmpfile:
44+
get_object(bucket, filename, out_file=tmpfile)
45+
tmpfile.seek(0)
46+
47+
if not filecmp.cmp(filename, tmpfile.name):
48+
raise Exception('Downloaded file != uploaded object')
49+
50+
print('Deleting object..')
51+
resp = delete_object(bucket, filename)
52+
if resp:
53+
print(json.dumps(resp, indent=2))
54+
print('Done')
55+
56+
57+
def create_service():
58+
# Get the application default credentials. When running locally, these are
59+
# available after running `gcloud init`. When running on compute
60+
# engine, these are available from the environment.
61+
credentials = GoogleCredentials.get_application_default()
62+
63+
# Construct the service object for interacting with the Cloud Storage API -
64+
# the 'storage' service, at version 'v1'.
65+
# You can browse other available api services and versions here:
66+
# http://g.co/dev/api-client-library/python/apis/
67+
return discovery.build('storage', 'v1', credentials=credentials)
68+
69+
70+
def upload_object(bucket, filename, readers, owners):
71+
service = create_service()
72+
73+
# This is the request body as specified:
74+
# http://g.co/cloud/storage/docs/json_api/v1/objects/insert#request
75+
body = {
76+
'name': filename,
77+
}
78+
79+
# If specified, create the access control objects and add them to the
80+
# request body
81+
if readers or owners:
82+
body['acl'] = []
83+
84+
for r in readers:
85+
body['acl'].append({
86+
'entity': 'user-%s' % r,
87+
'role': 'READER',
88+
'email': r
89+
})
90+
for o in owners:
91+
body['acl'].append({
92+
'entity': 'user-%s' % o,
93+
'role': 'OWNER',
94+
'email': o
95+
})
96+
97+
# Now insert them into the specified bucket as a media insertion.
98+
# http://g.co/dev/resources/api-libraries/documentation/storage/v1/python/latest/storage_v1.objects.html#insert
99+
with open(filename, 'rb') as f:
100+
req = service.objects().insert(
101+
bucket=bucket, body=body,
102+
# You can also just set media_body=filename, but # for the sake of
103+
# demonstration, pass in the more generic file handle, which could
104+
# very well be a StringIO or similar.
105+
media_body=http.MediaIoBaseUpload(f, 'application/octet-stream'))
106+
resp = req.execute()
107+
108+
return resp
109+
110+
111+
def get_object(bucket, filename, out_file):
112+
service = create_service()
113+
114+
# Use get_media instead of get to get the actual contents of the object.
115+
# http://g.co/dev/resources/api-libraries/documentation/storage/v1/python/latest/storage_v1.objects.html#get_media
116+
req = service.objects().get_media(bucket=bucket, object=filename)
117+
118+
downloader = http.MediaIoBaseDownload(out_file, req)
119+
120+
done = False
121+
while done is False:
122+
status, done = downloader.next_chunk()
123+
print("Download {}%.".format(int(status.progress() * 100)))
124+
125+
return out_file
126+
127+
128+
def delete_object(bucket, filename):
129+
service = create_service()
130+
131+
req = service.objects().delete(bucket=bucket, object=filename)
132+
resp = req.execute()
133+
134+
return resp
135+
136+
137+
if __name__ == '__main__':
138+
parser = argparse.ArgumentParser(
139+
description=__doc__,
140+
formatter_class=argparse.RawDescriptionHelpFormatter)
141+
parser.add_argument('filename', help='The name of the file to upload')
142+
parser.add_argument('bucket', help='Your Cloud Storage bucket.')
143+
parser.add_argument('--reader', action='append', default=[],
144+
help='Your Cloud Storage bucket.')
145+
parser.add_argument('--owner', action='append', default=[],
146+
help='Your Cloud Storage bucket.')
147+
148+
args = parser.parse_args()
149+
150+
main(args.bucket, args.filename, args.reader, args.owner)

storage/api/crud_object_test.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2016, Google, Inc.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
import re
15+
16+
from crud_object import main
17+
18+
19+
def test_main(cloud_config, capsys):
20+
main(cloud_config.storage_bucket, __file__)
21+
out, err = capsys.readouterr()
22+
23+
assert not re.search(r'Downloaded file [!]=', out)
24+
assert re.search(r'Uploading.*Fetching.*Deleting.*Done', out, re.DOTALL)

0 commit comments

Comments
 (0)