Allowing Users to Upload Files

Region ID

The REGION_ID is an abbreviated code that Google assigns based on the region you select when you create your app. The code does not correspond to a country or province, even though some region IDs may appear similar to commonly used country and province codes. For apps created after February 2020, REGION_ID.r is included in App Engine URLs. For existing apps created before this date, the region ID is optional in the URL.

Learn more about region IDs.

When you upload directly to Google Cloud Storage, you make an HTTP POST to a specific URL, which we'll describe in a moment. App Engine then uses a specific upload service to handle the post and write the file to Google Cloud Storage. When the file write is complete, App Engine notifies your app that the upload is complete. Because your app is invoked only upon completion, you can use this method to upload very large files, up to the current maximum of 100 Terabytes.

User upload of files directly to Google Cloud Storage is faster and more cost-effective than writing to Google Cloud Storage from your App Engine app, because this consumes instance hours and incurs cost. Moreover, the file write does not occur within a request to the application. Therefore it is exempt from the request timeout that would otherwise apply and allows uploads of very large files.

Implementing file uploads

To implement user file upload:

  1. Import CloudStorageTools:

    use google\appengine\api\cloud_storage\CloudStorageTools;
  2. Create the application specific upload URL, using the method CloudStorageTools::createUploadUrl() in your .php file as follows:

    $options = ['gs_bucket_name' => $my_bucket];
    $upload_url = CloudStorageTools::createUploadUrl('/upload/handler', $options);

    See createUploadUrl options for details about available options. Note that my_bucket will be YOUR_APP_ID. if using the default bucket.

  3. Note that you must start uploading to this URL within 10 minutes of its creation. Also, you cannot change the URL in any way - it is signed and the signature is checked before your upload begins.

  4. Use this URL as the action for the form you use to accept uploads, for example:

    <form action="{{ upload_url }}" enctype="multipart/form-data" method="post">
        Files to upload: <br>
       <input type="file" name="uploaded_files" size="40">
       <input type="submit" value="Send">

After the file(s) upload, a POST is made to the path specified as the first parameter to createUploadUrl; in the example above, this is /upload_handler.php. The PHP runtime forms the correct $_FILES super global, and tmp_filename refers to the filename of the newly uploaded file in Google Cloud Storage.

For example, suppose the content of upload_handler.php is the following:


Uploading a file called hello.txt might result in the following output:

array(1) {
  array(5) {
    ['name']=>    string(14) 'hello.txt'
    ['type']=>    string(10) 'text/plain'
    ['tmp_name']=>    string(73) 'gs://my_bucket/L2FwcHMtdXBsb2FkL2Jsb2JzL2IxNUFBVGNJNXNTd0VqR0tFSUtDRGxadGc'
    ['error']=>    int(0)
    ['size']=>    int(1452)

After the upload is complete, you can read the uploaded file using the gs:// stream wrapper. You use move_uploaded_file like you normally would for any other uploaded file, for example:

$file_name = $_FILES['uploaded_files']['name'];
$temp_name = $_FILES['uploaded_files']['tmp_name'];
move_uploaded_file($temp_name, "gs://${my_bucket}/${file_name}.txt");

createUploadUrl options

Valid createUploadUrl options are shown in the following table:

Option Description
max_bytes_per_blob Integer. Default value: unlimited. The value of the largest size allowed for an uploaded blob.
max_bytes_total Integer. Default value: unlimited. The total size of all uploaded blobs.
gs_bucket_name String. The name of a Google Cloud Storage bucket that the blobs should be uploaded to. If you don't specify a value, the blob is uploaded to the application's default bucket.