Загрузка файла на URL с подписью Google с PHP cURL - PullRequest
0 голосов
/ 10 июля 2020

Я пытаюсь загрузить файл на URL-адрес, подписанный Google, с помощью cURL в PHP.

У меня есть файл, отправляемый из формы, и я могу получить к нему доступ с помощью $ _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

Edit

Я пробовал это:

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

, но это просто приводит к сбою моей страницы.

Я думаю, что это может быть связано с тем, как я вызываю запрос, поэтому я хотел создать функцию cURL, которой я мог бы просто передавать URL-адрес и данные для всех моих запросов, например:

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

Тогда моя функция выглядит так:

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 пытается открыть ит.

введите описание изображения здесь

1 Ответ

0 голосов
/ 17 июля 2020

это то, что вы хотите: полностью удалить 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');

никогда не используйте режим r, всегда используйте rb режим (сокращение от «двоичный режим»), странные вещи случаются, если вы когда-либо использовали r режим на Windows, r - это сокращение от «текстовый режим» - если вам действительно нужен текстовый режим, используйте rt (и если вы действительно не знаете, что делаете, вам не нужен текстовый режим, к сожалению, это режим по умолчанию),

, но загруженный файл был странным. (...) Вот как выглядит файл, когда человек на другом конце этого API пытается его открыть.

ну, вы дали CURLOPT_POSTFIELDS ресурс. CURLOPT_POSTFIELDS принимает 2 вида аргументов: # 1: массив (для multipart/form-data запросов), # 2: строка (когда вы хотите указать необработанные данные тела сообщения), он не принимает ресурсы.

если бы api php curl был хорошо спроектирован, вы бы получили InvalidArgumentException или TypeError при предоставлении ресурса CURLOPT_POSTFIELDS. но это плохо спроектировано. вместо этого произошло то, что curl_setopt неявно преобразовал ваш ресурс в строку, следовательно, resource id #X, это то же самое, что и

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