2

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.
Tanaike
  • 181,128
  • 11
  • 97
  • 165
Willis
  • 599
  • 3
  • 25
  • Refer to this: [How can I upload files to GoogleDrive in “multipart” type by using Guzzle?](https://stackoverflow.com/questions/60837047/how-can-i-upload-files-to-googledrive-in-multipart-type-by-using-guzzle) – Willis Mar 25 '20 at 01:39

1 Answers1

6
  • 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.

halfer
  • 19,824
  • 17
  • 99
  • 186
Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • 1
    Actually I almost figure it out after I post this question several hours, but I really appreciate, you help me a lot, now I know how **boundary** works and how data actually transfer in "POST" method, if I use `google-api-php-client`, I won't learn this, this is one of the reason why I'm not using the `google-api-php-client`. Thank you so much! – Willis Mar 24 '20 at 05:07
  • @Bruce Xie Thank you for replying. I agree with your direction. Also at first, I created some applications without using the official goolgeapis. By this, when I actually used the googleapis, I could understand more about the googleapis. – Tanaike Mar 24 '20 at 05:12
  • @anaike Thank you! I also notice that we don't have to set the `Content-Length` header cause the curl tool will do it automatically. Another point is that `fopen()`, `fread()` and `fclose()` can be replaced with `file_get_contents()`. – Willis Mar 24 '20 at 05:39
  • @anaike I found we can't use `base_encode()`, otherwise if you upload image, you can't preview it. – Willis Mar 24 '20 at 06:32
  • @Bruce Xie Thank you for replying. In my environment, when the image file is uploaded using this modified script, I could confirm that the script worked and the image can be correctly shown. So I proposed this modification. But if in your environment, it cannot be used, I have to apologize for this. – Tanaike Mar 24 '20 at 06:35
  • Oh, I know why, I miss this line: `$data .= "Content-Transfer-Encoding: base64\r\n\r\n";` – Willis Mar 24 '20 at 06:39