Search code examples
phpgoogle-drive-apiphp-curlboundary

How can I upload files to GoogleDrive in "multipart" type by using php-curl?


I want to upload in using php curl other than google-api-php-client, but I really don't know how to do it, here is the documentation:Send a multipart upload request

Here is my code snippet, I stuck in CURLOPT_POSTFIELDS, can anybody help me with this?

public function uploadByCurl($uploadFilePath, $accessToken){
    $ch = curl_init();
    $mimeType = $this->getMimeType($uploadFilePath);
    $options = [
        CURLOPT_URL =>  'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart',
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POSTFIELDS => [
            'file' => new \CURLFile($uploadFilePath),
            // 'name' =>
        ],
        CURLOPT_HTTPHEADER => [
            'Authorization:Bearer ' . $accessToken,
            'Content-Type:' . $mimeType,
            'Content-Length:' . filesize($uploadFilePath),
        ],
        //In case you're in Windows, sometimes will throw error if not set SSL verification to false
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => 0,
    ];
    //In case you need a proxy
    //$options[CURLOPT_PROXY] = 'http://127.0.0.1:1087';

    curl_setopt_array($ch, $options);
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'Error:' . curl_error($ch);
    }
    curl_close ($ch);
    return $result;
}

I just don't know how to translate this to code(not familiar with multipart/related):

  • Metadata part. Must come first, and must have a Content-Type header set to application/json; charset=UTF-8. Add the file's metadata to this part in JSON format.
  • Media part. Must come second, and must have a Content-Type header, which may have any MIME type. Add the file's data to this part.

Solution

    • You want to upload a file using multipart/ralated with Drive API v3.
    • You want to achieve this using PHP CURL.
    • Your access token can be used for uploading the file to Google Drive.

    If my understanding is correct, how about this answer?

    Modification points:

    • In this case, I would like to propose to create the structure including the file and the metadata for multipart/ralated and request it.

    Modified script:

    When your script is modified, it becomes as follows.

    public function uploadByCurl($uploadFilePath, $accessToken){
        $handle = fopen($uploadFilePath, "rb");
        $file = fread($handle, filesize($uploadFilePath));
        fclose($handle);
    
        $boundary = "xxxxxxxxxx";
        $data = "--" . $boundary . "\r\n";
        $data .= "Content-Type: application/json; charset=UTF-8\r\n\r\n";
        $data .= "{\"name\": \"" . basename($uploadFilePath) . "\", \"mimeType\": \"" . mime_content_type($uploadFilePath) . "\"}\r\n";
        $data .= "--" . $boundary . "\r\n";
        $data .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $data .= base64_encode($file);
        $data .= "\r\n--" . $boundary . "--";
    
        $ch = curl_init();
        $options = [
            CURLOPT_URL =>  'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart',
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POSTFIELDS => $data,
            CURLOPT_HTTPHEADER => [
                'Authorization:Bearer ' . $accessToken,
                'Content-Type:multipart/related; boundary=' . $boundary,
            ],
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => 0,
        ];
        curl_setopt_array($ch, $options);
        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            echo 'Error:' . curl_error($ch);
        }
        curl_close ($ch);
        return $result;
    }
    
    • At this modified script, the filename and mimeType are retrieved from $uploadFilePath.

    Note:

    • Multipart upload can upload files less than 5 MB size. Please be careful this.

    References:

    • Perform a multipart upload

      Multipart upload: uploadType=multipart. For quick transfer of a small file (5 MB or less) and metadata that describes the file, all in a single request.