Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

I've been implementing user file uploads for an App Engine application when I hit a problem on my local development server. Even on successful uploads from the client side, I would always get a 500 error on the server side, like so:
 Error
ERROR 2017-06-01 23:30:46,394 module.py:899] Request to '/_ah/upload/ahNkZXZ-dHJhdmVsbWljcm9ibG9nciILEhVfX0Jsb2JVcGxvYWRTZXNzaW9uX18YgICAgIDIowoM' failed


The code to create the upload URL looked like this:
 PHP
$options = [
'gs_bucket_name' => '#default#',
'url_expiry_time_seconds' => 86400
];
$url = CloudStorageTools::createUploadUrl('/admin/api/assets/upload', $options);


So that seemed to be correct, but as I later found out it wasn't. To track down the problem, I had to enable debug output for the dev server itself. This is done by passing --dev_appserver_log_level=debug when running the dev_appserver.py script. For me the whole command line looked like this:
 Dev Server
dev_appserver.py --port=8080 -A=travelmicroblog --runtime=php55 --log_level=debug --dev_appserver_log_level=debug app.yaml


Now I was getting more detailed error messages, including a stack trace, like so:
 Error
ERROR 2017-06-01 23:34:32,927 module.py:897] Request to '/_ah/upload/ahNkZXZ-dHJhdmVsbWljcm9ibG9nciILEhVfX0Jsb2JVcGxvYWRTZXNzaW9uX18YgICAgIDonQoM' failed
Traceback (most recent call last):
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/module.py", line 890, in _handle_request
ret = handler.handle(match, environ, wrapped_start_response)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/wsgi_handler.py", line 60, in handle
return self._wsgi_app(environ, start_response)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/blob_upload.py", line 598, in __call__
self.store_blob_and_transform_request(environ)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/blob_upload.py", line 559, in store_blob_and_transform_request
bucket_name=bucket_name)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/blob_upload.py", line 452, in store_and_build_forward_message
content_type, gs_filename, blob_file, filename)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/blob_upload.py", line 265, in store_gs_file
{'content-type': content_type})
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/api/datastore.py", line 2777, in inner_wrapper
return func(*args, **kwds)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/ext/cloudstorage/cloudstorage_stub.py", line 161, in post_start_creation
common.validate_file_path(filename)
File "/Volumes/Data HD/Personal/google-cloud-sdk/platform/google_appengine/google/appengine/ext/cloudstorage/common.py", line 286, in validate_file_path
'but got %s' % path)
ValueError: Path should have format /bucket/filename but got /#default#/fake-9RB3va819BclBVNwwjrE7g==




The final message in the output was key here...
 Error
ValueError: Path should have format /bucket/filename but got /#default#/fake-9RB3va819BclBVNwwjrE7g==


After some experimenting and re-reading the documentation I realised that the default bucket name '#default#'can't be used in this case. Even though much of the PHP runtime does support this shorthand expression, when working with the CloudStorageTools class, you have to provide the actual bucket name.

I still wanted to use the default bucket, so used the CloudStorageTools::getDefaultGoogleStorageBucketName() function to retrieve it. My $options array now looked like this:
 PHP
$options = [
'gs_bucket_name' => CloudStorageTools::getDefaultGoogleStorageBucketName(),
'url_expiry_time_seconds' => 86400
];


Once I made that change, all of my uploads started working!

-i

Did you like this post or found it useful? Considering supporting this Blog to keep its web servers running, any amount helps! Thanks!
Have comments or feedback on what I wrote? Please share them below!
comments powered by Disqus
Other posts you may like...