Home » Php » azure – PHP Upload PDF to Google Drive API

azure – PHP Upload PDF to Google Drive API

Posted by: admin July 12, 2020 Leave a comment

Questions:

I have website created in PHP. Basically it is a send document kind of project. It uses a document store in Azure I will call and send it into Azure. Now I want to send in email as well as store in Google drive.

So it should be stored to drive with public access. I have create following code. It works properly I don’t want any input from user.

  $client->setAccessToken($_SESSION['accessToken']);
    $service = new Google_DriveService($client);
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $file = new Google_DriveFile();
    foreach ($files as $file_name) {
        $file_path = 'files/'.$file_name;
        $mime_type = finfo_file($finfo, $file_path);
        $file->setTitle($file_name);
        $file->setDescription('This is a '.$mime_type.' document');
        $file->setMimeType($mime_type);
        $service->files->insert(
            $file,
            array(
                'data' => file_get_contents($file_path),
                'mimeType' => $mime_type
            )
        );
    }
    finfo_close($finfo);

I want upload from Azure URL using cURL or using API. When mail send it is automatically uploaded to drive at the same time.

Question Update

I have function to send a mail this is work perfectly. I would like to store an attachment to google drive and retrieve path store that path in to database.

This all work will be based on API no user interaction required. That file is PDF in formate and not specific bytes its different as per data of file.

Issue :

When I upload a file to Drive original file name is rename to untitled. Here is code.

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

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

    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    //curl_setopt($ch, CURLOPT_POSTFIELDS, array("title" =>"newfile.txt"));
    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 : text/plain', 'Content-Length:' . filesize($filename),
                    'Authorization: Bearer ' . getAccessToken($credentials))
    );

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

    return json_decode($postResult, true);
}

==========================================

Updated code (Issue with Added code but still getting issue with Untitle.pdf in drive)

==========================================

<?php

$GAPIS = 'https://www.googleapis.com/';
$GAPIS_AUTH = $GAPIS . 'auth/';
$GOAUTH = 'https://accounts.google.com/o/oauth2/';

$CLIENT_ID = '709846732498-xxxxxxxx';
$CLIENT_SECRET = 'XXXXXXXXXXXXXX';
$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)
{

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

    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    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 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();

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

if (!isset($result['id']))
    throw new Exception(print_r($result));
else
    echo 'File copied successfuly (file Id: ' . $result['id'] . ')';

echo '<pre>'; print_r($result);
How to&Answers:

going by https://developers.google.com/drive/api/v3/simple-upload , this should work:

<?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/pdf', // todo: runtime detection?
                'Authorization: Bearer [YOUR_AUTH_TOKEN]' 
        ),
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => file_get_contents ( '/path/to/file.pdf' ),
        CURLOPT_RETURNTRANSFER => 1 
) );
try {
    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);

Answer:

I am still not completely sure i understand your question. Assuming you just want to upload a file in php or curl here are two options.

Uploading to Google drive is in two parts the first part you create the meta data that being the file name and basic information about your fine. The second part is where you upload the actual data of your file.

$fileMetadata = new Google_Service_Drive_DriveFile(array(
    'name' => 'My Report',
    'mimeType' => 'application/vnd.google-apps.spreadsheet'));
$content = file_get_contents('files/report.csv');
$file = $driveService->files->create($fileMetadata, array(
    'data' => $content,
    'mimeType' => 'text/csv',
    'uploadType' => 'multipart',
    'fields' => 'id'));
printf("File ID: %s\n", $file->id);

Code ripped from media upload

If you want to do this in curl inserting the meta data shouldnt be an issue your issue will be uploading the file itself. You will need to POST the metadata to create the empty file and capture its file-id. Then use the file-id for a content upload. You can find more information on the requests you will nee dot make here simple upload request.

The code will probably look something like this but again your going to have to pass the file id.

curl 
--silent 
--request POST 
--data-binary "@c:\temp\myfile.jpg"         
-OL MyFolder\myfile2.jpeg
-H "Slug: myfile3.jpg" 
-H "Authorization: Bearer [your access token here]" 
-H "Content-Type: image/jpeg {"fileid":"1234"}" 
"https://www.googleapis.com/upload/drive/v3/files?uploadType=media" 

Note i have not tested the upload in curl this is just a guess.

Answer:

You can use Logic Apps to send the file from Azure Blob storage to Google Drive as well as an email attachment.

https://docs.microsoft.com/en-us/azure/connectors/connectors-create-api-azureblobstorage

Alternatively files stored in Azure Blobs can be addresses with a public URL assuming you have the right permissions set on the container and/or blob.