Vasim Shaikh
Vasim Shaikh

Reputation: 4512

Create folder in root directiry of and upload file to that folder google drive api

I want to create folder in googledrive root directory using CURL. File is uploaded to drive but I need to create a folder and upload file to that folder.

As per @hanshenrik Code Create Folder is working Move file is not work

My Updated code :

$REDIRECT_URI = 'http' . ($_SERVER['SERVER_PORT'] == 80 ? '' : 's') . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME'];
$SCOPES = array($GAPIS_AUTH . 'drive', $GAPIS_AUTH . 'drive.file', $GAPIS_AUTH . 'userinfo.email', $GAPIS_AUTH . 'userinfo.profile');
$STORE_PATH = 'credentials.json';

function uploadFile($credentials, $filename, $targetPath,$folderId)
{

    global $GAPIS;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $GAPIS . 'upload/drive/v2/files?uploadType=media');

   //$content =  { title  "mypdf.pdf", description = "mypdf.pdf", mimeType = "application/pdf" };

   $contentArry = array('name' =>'veridoc', 'parents' => array('17dVe2GYpaHYFdFn1by5-TYKU1LXSAwkp'));
   $contentArry = json_encode($contentArry);



    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    //curl_setopt($ch, CURLOPT_POSTFIELDS,$contentArry);
    curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents($filename));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER,
            array('Content-Type : application/pdf','Content-Length:' . filesize($filename),'Authorization: Bearer ' . getAccessToken($credentials))
    );

    $postResult = curl_exec($ch);
    curl_close($ch);

    return json_decode($postResult, true);
}
function RenameUploadedFile($id,$credentials,$filename)
{

 $ch = curl_init();
    curl_setopt_array ( $ch, array (
            CURLOPT_URL => 'https://www.googleapis.com/drive/v3/files/' . urlencode ( $id ),
            CURLOPT_POST => 1,
            CURLOPT_RETURNTRANSFER => true,     
            CURLOPT_POSTFIELDS => json_encode ( array (
                    'name' => $filename  
            ) ),
            CURLOPT_CUSTOMREQUEST => 'PATCH',
            CURLOPT_HTTPHEADER => array (
                    'Content-Type : application/json',
                    'Authorization: Bearer ' . getAccessToken ( $credentials ) 
            ) 

    ) );
    curl_exec($ch);
    curl_close($ch);
    return true;
}

  function CreateGDFolder($credentials,$foldername)
    {


            $curl = curl_init();
            curl_setopt_array ( $curl, array (
            CURLOPT_URL => 'https://www.googleapis.com/drive/v3/files',
            CURLOPT_POST => 1,
            CURLOPT_RETURNTRANSFER => true,             
            CURLOPT_POSTFIELDS => json_encode ( array (
                // Earlier it was title changed to name
                "name" => $foldername,
                "mimeType" => "application/vnd.google-apps.folder"

            ) ),
            // Earlier it was PATCH changed to post
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_HTTPHEADER => array (
                'Content-Type : application/json',
                'Authorization: Bearer ' . getAccessToken ( $credentials ) 
            ) 

            ) );

           $response = curl_exec($curl);

        return json_decode($response, true);
}



function getStoredCredentials($path)
{

    $credentials = json_decode(file_get_contents($path), true);

    if (isset($credentials['refresh_token']))
    {   
        return $credentials;
    }


    $expire_date = new DateTime();
    $expire_date->setTimestamp($credentials['created']);
    $expire_date->add(new DateInterval('PT' . $credentials['expires_in'] . 'S'));

    $current_time = new DateTime();

    if ($current_time->getTimestamp() >= $expire_date->getTimestamp())
    {
        $credentials = null;
        unlink($path);
    }

    return $credentials;
}

function storeCredentials($path, $credentials)
{

    $credentials['created'] = (new DateTime())->getTimestamp();
    file_put_contents($path, json_encode($credentials));
    return $credentials;
}

function requestAuthCode()
{

    global $GOAUTH, $CLIENT_ID, $REDIRECT_URI, $SCOPES;
    $url = sprintf($GOAUTH . 'auth?scope=%s&redirect_uri=%s&response_type=code&client_id=%s&approval_prompt=force&access_type=offline',
            urlencode(implode(' ', $SCOPES)), urlencode($REDIRECT_URI), urlencode($CLIENT_ID)
    );
    header('Location:' . $url);
}

function requestAccessToken($access_code)
{

    global $GOAUTH, $CLIENT_ID, $CLIENT_SECRET, $REDIRECT_URI;
    $url = $GOAUTH . 'token';
    $post_fields = 'code=' . $access_code . '&client_id=' . urlencode($CLIENT_ID) . '&client_secret=' . urlencode($CLIENT_SECRET)
            . '&redirect_uri=' . urlencode($REDIRECT_URI) . '&grant_type=authorization_code';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
    curl_setopt($ch, CURLOPT_POST, true);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);

    $result = curl_exec($ch);

    curl_close($ch);

    return json_decode($result, true);
}

function getAccessToken($credentials)
{

    $expire_date = new DateTime();
    $expire_date->setTimestamp($credentials['created']);
    $expire_date->add(new DateInterval('PT' . $credentials['expires_in'] . 'S'));

    $current_time = new DateTime();

    if ($current_time->getTimestamp() >= $expire_date->getTimestamp())
        return $credentials['refresh_token'];
    else
        return $credentials['access_token'];

}

function authenticate()
{

    global $STORE_PATH;

    if (file_exists($STORE_PATH))
        $credentials = getStoredCredentials($STORE_PATH);
    else
        $credentials = null;

    if (!(isset($_GET['code']) || isset($credentials)))
        requestAuthCode();

    if (!isset($credentials))
        $credentials = requestAccessToken($_GET['code']);

    if (isset($credentials) && isset($credentials['access_token']) && !file_exists($STORE_PATH))
        $credentials = storeCredentials($STORE_PATH, $credentials);

    return $credentials;
}   

$credentials = authenticate();

$folderresponse=CreateGDFolder($credentials,"veridoc");
$folderID= $folderresponse['id'];
$folder_id=$folderID;
$filename="veridoc".date('_Y_m_d_H_i_s').".pdf";

$result = uploadFile($credentials, 'veridoc.pdf', '',$folderID);

// File rename to original

$id=$result['id'];
$file_id=$id;


if(isset($folderID)){

//Upload a file 
if(RenameUploadedFile($id,$credentials,$filename))
{
echo "We have uploaded ".$filename." to drive";
}
else{
echo "can't rename file";
}
}



try {
    $ch = curl_init ();
    curl_setopt_array ( $ch, array (
            CURLOPT_URL => 'https://www.googleapis.com/upload/drive/v3/files/' . urlencode ( $file_id ),
            CURLOPT_POST => 1,
            CURLOPT_RETURNTRANSFER => true,     
            CURLOPT_POSTFIELDS => json_encode (array(
            'addParents' => $folder_id,
            'removeParents' => 'root',
            'fields' => 'id, parents') ),
            CURLOPT_CUSTOMREQUEST => 'PATCH',
            CURLOPT_HTTPHEADER => array (
                    'Content-Type : application/pdf',
                    'Authorization: Bearer ' . getAccessToken ( $credentials ) 
            ) 

    ) );
    $resp = curl_exec ( $ch );
    $parsed = json_decode ( $resp, true );

} finally{
    curl_close ( $ch );
}

Upvotes: 2

Views: 5549

Answers (4)

Payam Khaninejad
Payam Khaninejad

Reputation: 7996

This is my working example:

To connect Google Driver:

public function connect(Request $request)
    {
        $user = Auth::user();

        $client = new \Google_Client();
        $client->setHttpClient(new \GuzzleHttp\Client(['verify' => false]));
        $client->setClientId('xxxx');
        $client->setClientSecret('xxxxxx');
        $client->setRedirectUri(url('copywriter/connect'));
        $client->setAccessType('offline');
        $client->setApprovalPrompt('force');
        $client->setScopes(array('https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.appfolder'));
        if (isset($request->code)) {
            $authCode = trim($request->code);
            $accessToken = $client->authenticate($authCode);
            $copywriter->gd_access_token=json_encode($accessToken, JSON_PRETTY_PRINT);
            $copywriter->save();
        } else {
            $authUrl = $client->createAuthUrl();
            return redirect($authUrl);
        }

        $found=$this->search_gd("files");
        if (!isset($found['file_id'])) {
            $found=$this->create_folder_gd("copify_files");
            $copywriter->gd_folder_id=$found["file_id"];
            $copywriter->save();
        }
        return redirect(route("copywriter.index"));
    }

Send to Google Drive

    public function send_to_gd($name)
        {
            $user = Auth::user();
            $copywriter=Copywriter::where('user_id', $user->id)->first();
            $folderId = $copywriter->gd_folder_id;
            $client=$this->getClient();
            $service = new \Google_Service_Drive($client);
            $fileMetadata = new \Google_Service_Drive_DriveFile(array(
            'name' => $name,'mimeType' => 'application/vnd.google-apps.document','parents' => array($folderId)));
            $file = $service->files->create($fileMetadata, array(
            'mimeType' => 'application/vnd.google-apps.document',
            'uploadType' => 'multipart',
            'fields' => 'id'));
            return $file->id;
        }

Client of Request:

public function getClient($user=null)
    {
        if ($user==null) {
            $user = Auth::user();
        }
        $copywriter=Copywriter::where('user_id', $user->id)->first();
        $client = new \Google_Client();
        $client->setHttpClient(new \GuzzleHttp\Client(['verify' => false]));
        $client->setClientId('xxxx');
        $client->setClientSecret('xxxxx');
        $client->setRedirectUri(url('copywriter/connect'));
        $client->setAccessType('offline');
        $client->setApprovalPrompt('force');
        $client->setScopes(array('https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.appfolder'));


        $data=json_decode($copywriter->gd_access_token, true);

        $client->setAccessToken($data);

        // Refresh the token if it's expired.
        if ($client->isAccessTokenExpired()) {
            $oldAccessToken=$client->getAccessToken();
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
            $accessToken=$client->getAccessToken();
            $accessToken['refresh_token']=$oldAccessToken['refresh_token'];

            $copywriter->gd_access_token=json_encode($accessToken, JSON_PRETTY_PRINT);
            $copywriter->save();
        }
        return $client;
    }

Search in Google Drive

public function search_gd($name)
    {
        $client=$this->getClient();
        $service = new \Google_Service_Drive($client);
        $pageToken = null;
        do {
            $response = $service->files->listFiles(array(
        'q' => "mimeType='application/vnd.google-apps.folder' and name='".$name."'",
        'spaces' => 'drive',
        'pageToken' => $pageToken,
        'fields' => 'nextPageToken, files(id, name)',
    ));
            foreach ($response->files as $file) {
                return ['file_name'=>$file->name,'file_id'=>$file->id];
                printf("Found file: %s (%s)\n", $file->name, $file->id);
            }
            if (isset($repsonse)) {
                $pageToken = $repsonse->pageToken;
            }
        } while ($pageToken != null);
    }

Create a folder on Google Drive

public function create_folder_gd($name)
    {
        $client=$this->getClient();
        $service = new \Google_Service_Drive($client);
        $fileMetadata = new \Google_Service_Drive_DriveFile(array(
    'name' => $name,
    'mimeType' => 'application/vnd.google-apps.folder'));
        $file = $service->files->create($fileMetadata, array(
    'fields' => 'id'));
        return ['file_name'=>$name,'file_id'=>$file->id];
    }

Create a document on Google Drive:

public function create_document($name, $content_id=null)
    {
        $user = Auth::user();
        $copywriter=Copywriter::where('user_id', $user->id)->first();
        $folderId = $copywriter->gd_folder_id;
        $client=$this->getClient();
        $service = new \Google_Service_Drive($client);
        $fileMetadata = new \Google_Service_Drive_DriveFile(array(
      'name' => $name,'mimeType' => 'application/vnd.google-apps.document','parents' => array($folderId)));
        $file = $service->files->create($fileMetadata, array(
      'mimeType' => 'application/vnd.google-apps.document',
      'uploadType' => 'multipart',
      'fields' => 'id'));
        if ($content_id!=null) {
            $content=Content::findOrFail($content_id);
            $content->file_id=$file->id;
            $content->save();
        }
        return ['file_name'=>$name,'file_id'=>$file->id];
    }

My Models is Copywriter and Content replace it with your's.

Upvotes: 5

hanshenrik
hanshenrik

Reputation: 21483

going by the documentation on folders here https://developers.google.com/drive/api/v2/folder , seems like you create folders by uploading an empty "file" with the content-type set to application/vnd.google-apps.folder.

here is documentation on how to upload files, in a simple way: https://developers.google.com/drive/api/v2/simple-upload

problem with that upload method is the the created file (or folder, in this case) won't have a name, it will just be called untitled<whatever>, so finally, here's documentation on how to rename files: https://developers.google.com/drive/api/v3/reference/files/update (or in this case, a folder)

putting it all together, you'll probably end up with something like:

<?php
$ch = curl_init ();
curl_setopt_array ( $ch, array (
        CURLOPT_URL => 'https://www.googleapis.com/upload/drive/v3/files?uploadType=media',
        CURLOPT_HTTPHEADER => array (
                'Content-Type: application/vnd.google-apps.folder',
                'Authorization: Bearer '.getAccessToken ( $credentials )  
        ),
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => '', // "empty file"
        CURLOPT_RETURNTRANSFER => 1 
) );
try {
    // this will create the folder, with no name
    if (false === ($resp = curl_exec ( $ch ))) {
        throw new \RuntimeException ( 'curl error ' . curl_errno ( $ch ) . ": " . curl_error ( $ch ) );
    }
    $parsed = json_decode ( $resp, true );
    if (! $parsed || $parsed ['code'] !== 200) {
        throw new \RuntimeException ( 'google api error: ' . $resp );
    }
    $id = $parsed ['id'];
    // now to give the folder a name:
    curl_setopt_array ( $ch, array (
            CURLOPT_URL => 'https://www.googleapis.com/drive/v3/files/' . urlencode ( $id ),
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => json_encode ( array (
                    'name' => 'the_folders_name' 
            ) ),
            CURLOPT_CUSTOMREQUEST => 'PATCH',
            CURLOPT_HTTPHEADER => array (
                    'Content-Type : application/json',
                    'Authorization: Bearer ' . getAccessToken ( $credentials ) 
            ) 

    ) );

    if (false === ($resp = curl_exec ( $ch ))) {
        throw new \RuntimeException ( 'curl error ' . curl_errno ( $ch ) . ": " . curl_error ( $ch ) );
    }
    $parsed = json_decode ( $resp, true );
    if (! $parsed || $parsed ['code'] !== 200) {
        throw new \RuntimeException ( 'google api error: ' . $resp );
    }
} finally{
    curl_close ( $ch );
}
var_dump ( $resp );

and finally, to move files inside this folder, send a PATCH request to https://www.googleapis.com/upload/drive/v3/files/<file_you_want_to_move_id> with the folder's id as the addParents parameter of the request body, eg something like:

<?php
try {
    $ch = curl_init ();
    curl_setopt_array ( $ch, array (
            CURLOPT_URL => 'https://www.googleapis.com/upload/drive/v3/files/' . urlencode ( $file_id ),
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => json_encode ( array (
                    'addParents' => $folder_id,
                    'removeParents'=> 'root',


            ) ),
            CURLOPT_CUSTOMREQUEST => 'PATCH',
            CURLOPT_HTTPHEADER => array (
                    'Content-Type : application/json',
                    'Authorization: Bearer ' . getAccessToken ( $credentials ) 
            ) 

    ) );
    if (false === ($resp = curl_exec ( $ch ))) {
        throw new \RuntimeException ( 'curl error ' . curl_errno ( $ch ) . ": " . curl_error ( $ch ) );
    }
    $parsed = json_decode ( $resp, true );
    if (! $parsed || $parsed ['code'] !== 200) {
        throw new \RuntimeException ( 'google api error: ' . $resp );
    }
} finally{
    curl_close ( $ch );
}

Upvotes: 2

Wellwisher
Wellwisher

Reputation: 472

See this if it is working. I have made changes like "name" => "", CURLOPT_CUSTOMREQUEST => 'POST',

function CreateGDFolder($credentials)
    {
        $ch = curl_init();
        curl_setopt_array ( $ch, array (
        CURLOPT_URL => 'https://www.googleapis.com/drive/v3/files',
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => json_encode ( array (
            // Earlier it was title changed to name
            "name" => "pets",
            "mimeType" => "application/vnd.google-apps.folder"

        ) ),
        // Earlier it was PATCH changed to post
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_HTTPHEADER => array (
            'Content-Type : application/json',
            'Authorization: Bearer ' . getAccessToken ( $credentials ) 
        ) 

        ) );

        $response=curl_exec($ch);
        $response = json_decode($response, true);
        print_r($response); 
        curl_close($ch);
    }

See its working fine for me

Upvotes: 0

user6299088
user6299088

Reputation:

This will help You:

https://developers.google.com/drive/api/v3/folder

Creating a folder:

In the Drive API, a folder is essentially a file — one identified by the special folder MIME type application/vnd.google-apps.folder. You can create a new folder by inserting a file with this MIME type and a folder title. Do not include an extension when setting a folder title.

$fileMetadata = new Google_Service_Drive_DriveFile(array(
    'name' => 'Invoices',
    'mimeType' => 'application/vnd.google-apps.folder'));
$file = $driveService->files->create($fileMetadata, array(
    'fields' => 'id'));
printf("Folder ID: %s\n", $file->id);

Inserting a file in a folder:

To insert a file in a particular folder, specify the correct ID in the parents property of the file, as shown:

$folderId = '0BwwA4oUTeiV1TGRPeTVjaWRDY1E';
$fileMetadata = new Google_Service_Drive_DriveFile(array(
    'name' => 'photo.jpg',
    'parents' => array($folderId)
));
$content = file_get_contents('files/photo.jpg');
$file = $driveService->files->create($fileMetadata, array(
    'data' => $content,
    'mimeType' => 'image/jpeg',
    'uploadType' => 'multipart',
    'fields' => 'id'));
printf("File ID: %s\n", $file->id);

The parents property can be used when creating a folder as well to create a subfolder.

Moving files between folders: To add or remove parents for an exiting file, use the addParents and removeParents query parameters on the files.update method.

Both parameters may be used to move a file from one folder to another, as shown:

$fileId = '1sTWaJ_j7PkjzaBWtNc3IzovK5hQf21FbOw9yLeeLPNQ';
$folderId = '0BwwA4oUTeiV1TGRPeTVjaWRDY1E';
$emptyFileMetadata = new Google_Service_Drive_DriveFile();
// Retrieve the existing parents to remove
$file = $driveService->files->get($fileId, array('fields' => 'parents'));
$previousParents = join(',', $file->parents);
// Move the file to the new folder
$file = $driveService->files->update($fileId, $emptyFileMetadata, array(
    'addParents' => $folderId,
    'removeParents' => $previousParents,
    'fields' => 'id, parents'));

Upvotes: 2

Related Questions