簡體   English   中英

使用 PHP cURL 將文件上傳到 Google 簽名的 URL

[英]Uploading a file to Google Signed URL with PHP cURL

我正在嘗試使用 PHP 中的 cURL 將文件上傳到 Google 簽名的 URL。

我有從表單發布的文件,並且可以使用 $_FILES var 訪問它。

但是,實際上傳的文件不是正確的文件,我認為這與我處理 tmp 文件的方式有關。

$file_name = $_FILES['file']['name'];
$temp_name = $_FILES['file']['tmp_name'];

// $file = fopen($temp_name, 'r');
// $file = realpath($temp_name);

$request = curl_init($request_url);

curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $file);
curl_setopt($request, CURLOPT_HTTPHEADER, array('Content-Type:text/plain','Authorization:'.$token));
curl_setopt($request, CURLOPT_CUSTOMREQUEST, 'PUT');

$response = curl_exec($request);
$errors = curl_error($request);
curl_close($request);

var_dump($response);
var_dump($errors);

以下內容按預期使用內容類型文本而不是音頻,即使它是一個 wav 文件。

curl -v -X PUT --upload-file file.wav --header "Content-Type: text/plain" request_url

編輯

我試過這個:

$file = new CurlFile($temp_name,$mime_type,$file_name);

但這只是讓我的頁面完全崩潰。

我認為這可能與我調用請求的方式有關,所以我想創建一個 cURL function 我可以將 url 傳遞給我的所有請求,例如:

$file = new CurlFile($temp_name,$mime_type,$file_name);
$result = curl_request($conn,$signed_url,$file,'text/plain','PUT');

那么我的function是這樣的:

function curl_request($conn,$request_url,$request_data,$content_type,$request_type){
    $api_username = 'API username';
    $stmt = $conn->prepare("SELECT * FROM config WHERE setting=:setting");
    $stmt->bindParam(':setting', $api_username);
    $stmt->execute();
    $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
    foreach($stmt->fetchAll() as $key=>$row) {
        $username = $row['value'];
    }
    $api_key = 'API key';
    $stmt = $conn->prepare("SELECT * FROM config WHERE setting=:setting");
    $stmt->bindParam(':setting', $api_key);
    $stmt->execute();
    $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
    foreach($stmt->fetchAll() as $key=>$row) {
        $key = $row['value'];
    }
    
    $data = array(
        'username' => $username,
        'password' => $key
    );
    $payload = json_encode($data);

    $initial_request = curl_init('https://example.com/auth');
    curl_setopt($initial_request, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($initial_request, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($initial_request, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));

    $initial_response = curl_exec($initial_request);
    $initial_errors = curl_error($initial_request);

    curl_close($initial_request);
    
    $decoded_response = (array)json_decode($initial_response);
    $token = $decoded_response['token'];
    
    $request = curl_init($request_url);
    
    curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($request, CURLOPT_POSTFIELDS, $request_data);
    curl_setopt($request, CURLOPT_HTTPHEADER, array('Content-Type:'.$content_type,'Authorization:'.$token));
    curl_setopt($request, CURLOPT_CUSTOMREQUEST, $request_type);
    
    $response = curl_exec($request);
    $errors = curl_error($request);
    curl_close($request);
    
    if(empty($errors)){
        return $response;
    }else{
        return $errors;
    }
}

這在我有$file = fopen($temp_name, 'r');時有效但上傳的文件是一個奇怪的文件。

編輯 2

這是 API 另一端的人試圖打開文件時的樣子。

在此處輸入圖像描述

這就是您想要的:完全刪除 CURLOPT_POSTFIELDS,並將CURLOPT_CUSTOMREQUEST=>'PUT'替換為CURLOPT_UPLOAD=>1並將'r'替換為'rb' ,並使用 CURLOPT_INFILE (您應該使用 INFILE 而不是 POSTFIELDS),

$fp = fopen($_FILES['file']['tmp_name'], "rb");
curl_setopt_array($ch,array(
CURLOPT_UPLOAD=>1,
CURLOPT_INFILE=>$fp,
CURLOPT_INFILESIZE=>$_FILES['file']['size']
));

這在我有 $file = fopen($temp_name, 'r'); 時有效

never use the r mode, always use the rb mode (short for "binary mode"), weird things happen if you ever use the r mode on Windows, r is short for "text mode" - if you actually want text mode, use rt (除非你真的知道你在做什么,否則你永遠不想要文本模式,不幸的是它是默認模式),

但上傳的文件是一個奇怪的文件。 (...) 這是 API 另一端的人試圖打開文件時的樣子。

好吧,你給了 CURLOPT_POSTFIELDS 一個資源。 CURLOPT_POSTFIELDS 接受 2 種 arguments,#1:一個數組(用於multipart/form-data請求),#2:一個字符串(用於指定原始帖子正文數據時),它不接受資源。

如果 php curl api 設計良好,則在提供 CURLOPT_POSTFIELDS 資源時會收到 InvalidArgumentException 或 TypeError 但它的設計並不好。 相反,發生的事情是 curl_setopt 隱式地將您的資源轉換為字符串,因此resource id #X ,它與做

curl_setopt($request, CURLOPT_POSTFIELDS, (string) fopen(...));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM