python --versionpip show google-cloud, pip show google-<service> or pip freezeTraceback (most recent call last):
[...]
File "<path-to-my-app>/views/__init__.py", line 64, in get_upload_url
blob.make_public()
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/storage/blob.py", line 1141, in make_public
self.acl.all().grant_read()
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/storage/acl.py", line 359, in all
return self.entity('allUsers')
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/storage/acl.py", line 314, in entity
if self.has_entity(entity):
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/storage/acl.py", line 265, in has_entity
self._ensure_loaded()
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/storage/acl.py", line 208, in _ensure_loaded
self.reload()
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/storage/acl.py", line 411, in reload
found = client._connection.api_request(method='GET', path=path)
File "<path-to-my-venv>/lib/python3.6/site-packages/google/cloud/_http.py", line 303, in api_request
error_info=method + ' ' + url)
google.cloud.exceptions.NotFound: 404 Not Found (GET https://www.googleapis.com/storage/v1/b/<my-bucket>/o/<my-object>/acl)
def example():
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
blob.make_public()
upload_url = blob.create_resumable_upload_session()
return upload_url
Everything works just fine without blob.make_public()
@ndrbrt You need to create the blob / object before you can make it public.
@dhermes Isn't blob = bucket.blob(blob_name)supposed to do just that?
Also, the example in the docs is very similar: https://cloud.google.com/storage/docs/access-control/making-data-public#storage-make-object-public-python
@ndrbrt Sorry for the confusion, bucket.blob does no network at all, it just creates a local Blob instance bound to the bucket. See the note in the docs. If you want to talk to the server, call blob.create().
The example linked assumes the blob already exists (on the server) in the bucket. @jonparrott Maybe a comment should be added to that document?
I am going to pre-emptively close, assuming the 404 is just because you hadn't called blob.create(). I'm happy to re-open / continue discussing if there are other issues. I'm open to suggestions on how to make it clearer what Bucket.blob() does, but I hope the note is the right call?
@dhermes AttributeError: 'Blob' object has no attribute 'create'
It seems, by reading the docs, it's just the bucket that has that method, not the blob. (Am I right?)
At this point I'm wondering when exactly my blob is created.. Might be it's created only when I call the upload URL from the resumable upload session with a PUT request from my client?
If so I can just send another request at that point to make that (then-already-created) blob public, but I wish there was a way to do it previously, without adding others http calls.
Btw thank you for your time
@ndrbrt You are correct that Blob instances are created by uploading them, via Blob.upload_from_file, Blob.upload_from_filename, or Blob.upload_from_string.
Blob.make_public is a "convenience wrapper" which updates the blob's ACL and saves it via an API request. You can bypass the extra API call by updating the blob's ACL yourself before calling one of the upload methods. E.g.:
blob = bucket.blob('my-blob-name')
blob.acl.all().grant_read()
blob.upload_from_filename('/path/to/blob/contents.txt')
Ah, so sorry for the wrong information.
@tseaver If I call it before the upload method it actually raises the same error. I'll probably end up making another request once the upload is done.
Thank you
@dhermes No worries, thank you anyway
@ndrbrt I don't mean to call make_public (which would make the API request). In my example above, I configured the blob's ACL the same way make_public does (blob.acl.all().grant_read()).
To future searchers this solution did not work for me either:
acl: No such object: myapp.appspot.com/thumbnails/small/file
For people arriving now, the solution given by @tseaver did not work for me either. The API did not respond with any error, but nothing was created.
If I upload before setting the public flag, I can upload the file, but I can't make it public after.
Uploads but doesn't make public:
blob = self.bucket.blob(destination_filename)
blob.upload_from_filename(source_file_path)
if make_public:
log.info('Trying to make file public')
blob.make_public()
Doesn't upload nor make public:
blob = self.bucket.blob(destination_filename)
if make_public:
log.info('Trying to make file public')
blob.acl.all().grant_read()
blob.upload_from_filename(source_file_path)
Both raise no errors.
EDIT: turns out the testing account and the app account had different permissions... Read more
@theholy7 the first example you have there should work.
I agree with the other comments here that it would be nice to be able to make a blob public before the file is actually uploaded.
Otherwise, when using create_resumable_upload_session() to generate a signed URL that the client subsequently uploads to, the system needs double back after the client has completed the upload to make it public (either using pub/sub or having the client send another request).
@whydna I sorted it. Turns out I had a permissions problem... classic.
Most helpful comment
@dhermes
AttributeError: 'Blob' object has no attribute 'create'It seems, by reading the docs, it's just the bucket that has that method, not the blob. (Am I right?)
At this point I'm wondering when exactly my blob is created.. Might be it's created only when I call the upload URL from the resumable upload session with a PUT request from my client?
If so I can just send another request at that point to make that (then-already-created) blob public, but I wish there was a way to do it previously, without adding others http calls.
Btw thank you for your time