Resumable uploading to Google Cloud Storage using PHP API

4.6k views Asked by At

I can successfully upload small size files to Google Cloud Storage using Google PHP API CLIENT, But cant upload a 300MB file. Return with memory error. Here is my code.

$storage = new Google_Service_Storage($client);

    $file_name = "filenameo.zip";

    $obj = new Google_Service_Storage_StorageObject();
    $obj->setName($file_name);

    $resp = $storage->objects->insert(
        "bucketname",
        $obj,
        array('name' => $file_name, 'data' => file_get_contents("300mb-file.zip"), 'uploadType' => 'media')
    );

i tried to change the UploadType to resumable .. but no luck. Please help.

Update: Used the Http as Brandon Yarbrough answer

receiving error (Fatal error: Uncaught exception 'Google_IO_Exception')

$storage = new Google_Service_Storage($client);

$obj = new Google_Service_Storage_StorageObject();

$obj->setName("filenameo.zip");
$obj->setBucket("bucketname");


$filen = "300mb-file.zip";
$mimetype = mime_content_type($filen);


$chunkSizeBytes = 1 * 1024 * 1024;
$client->setDefer(true);
$status = false;



$filetoupload = array('name' => $file_name, 'data' => $filen, 'uploadType' => 'media');

$request = $storage->objects->insert("bucketname",$obj,$filetoupload);

$media = new Google_Http_MediaFileUpload($client, $request, $mimetype, $chunkSizeBytes);
$handle = fopen($filen, "rb");
while (!$status && !feof($handle)) {
  $chunk = fread($handle, $chunkSizeBytes);
  $status = $media->nextChunk($chunk);
 }

$result = false;
if($status != false) {
  $result = $status;
}

fclose($handle);
// Reset to the client to execute requests immediately in the future.
$client->setDefer(false);
2

There are 2 answers

0
Fida Khattak On BEST ANSWER

Got it working with the below code.

    <?php

    require_once("google-api/autoload.php");
    //require_once("google-api/src/Google/Client.php");
    //require_once("google-api/src/Google/Service/Storage.php");
    //require_once("google-api/src/Google/Http/MediaFileUpload.php");
    session_start();
    /**
        * Connect to Google Cloud Storage API
    */
    $client = new Google_Client();
    $client->setApplicationName("ApplicationName");

    // $stored_access_token - your cached oauth access token 
    if( $stored_access_token ) {
        $client->setAccessToken( $stored_access_token );
    }

    $credential = new Google_Auth_AssertionCredentials(
    "[email protected]",
    array('https://www.googleapis.com/auth/devstorage.read_write'),
    file_get_contents("pathtokey/mykeyhere-7845b2eb92c9.p12")
    );

    $client->setAssertionCredentials($credential);
    if($client->getAuth()->isAccessTokenExpired()) {
        $client->getAuth()->refreshTokenWithAssertion($credential);
        // Cache the access token however you choose, getting the access token with $client->getAccessToken()
    }

    $storage = new Google_Service_Storage($client);



    if (isset($_GET['code'])) {
        if (strval($_SESSION['state']) !== strval($_GET['state'])) {
            die('The session state did not match.');
        }


        $client->authenticate($_GET['code']);
        $_SESSION['token'] = $client->getAccessToken();
        header('Location: ' . $redirect);
    }
    if (isset($_SESSION['token'])) {
        $client->setAccessToken($_SESSION['token']);
    }





    if ($client->getAccessToken()) {


            $sfilename = "mfile.zip"; //filename here
            $obj = new Google_Service_Storage_StorageObject();

            $obj->setName($sfilename);
            $obj->setBucket("myBucketS"); //bucket name here


            $filen = "pathtofile/uploadthis.zip";

            $mimetype = mime_content_type($filen);


            $chunkSizeBytes = 1 * 1024 * 1024;
            $client->setDefer(true);
            $status = false;

            $filetoupload = array('name' => $sfilename, 'uploadType' => 'resumable');

            $request = $storage->objects->insert("myBucketS",$obj,$filetoupload);

            $media = new Google_Http_MediaFileUpload($client, $request, $mimetype, null, true, $chunkSizeBytes);
            $media->setFileSize(filesize($filen));
            $handle = fopen($filen, "rb");

            while (!$status && !feof($handle)) {
                $chunk = fread($handle, $chunkSizeBytes);
                $status = $media->nextChunk($chunk);
            }

            $result = false;
            if($status != false) {
                $result = $status;
            }

            fclose($handle);
            // Reset to the client to execute requests immediately in the future.
            $client->setDefer(false);

        } else {
        // If the user hasn't authorized the app, initiate the OAuth flow
        $state = mt_rand();
        $client->setState($state);
        $_SESSION['state'] = $state;
        $authUrl = $client->createAuthUrl();
    }
    $_SESSION['token'] = $client->getAccessToken();

    print_r($status);


?>
0
Brandon Yarbrough On

file_get_contents literally loads the contents of the file into memory as a string. Your app presumably doesn't have an extra 300 MB of memory to work with.

Instead, I would recommend reading in the file in chunks and uploading those. Google_Http_MediaFileUpload is a useful tool for this. There's a good example here: https://developers.google.com/api-client-library/php/guide/media_upload

The important section is this bit:

$media = new Google_Http_MediaFileUpload($client, $request, ......, $chunkSizeBytes)
$handle = fopen("path/to/file", "rb");
while (!$status && !feof($handle)) {
  $chunk = fread($handle, $chunkSizeBytes);
  $status = $media->nextChunk($chunk);
 }