简体   繁体   English

使用 PHP cURL 将文件上传到 Google 签名的 URL

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

I am trying to upload a file to a Google Signed URL with cURL in PHP.我正在尝试使用 PHP 中的 cURL 将文件上传到 Google 签名的 URL。

I have the file being posted from a form and can access it with the $_FILES var.我有从表单发布的文件,并且可以使用 $_FILES var 访问它。

However the file that actually gets uploaded is not the right file and I think it is to do with how I am handling the tmp file.但是,实际上传的文件不是正确的文件,我认为这与我处理 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);

The following works as expected with content-type text instead of audio even though its a wav file.以下内容按预期使用内容类型文本而不是音频,即使它是一个 wav 文件。

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

Edit编辑

I have tried this:我试过这个:

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

but this just crashes my page altogether.但这只是让我的页面完全崩溃。

I think it may be to do with how I am calling the request, so I wanted to create a cURL function that I can just pass the url and data to for all my requests like so:我认为这可能与我调用请求的方式有关,所以我想创建一个 cURL function 我可以将 url 传递给我的所有请求,例如:

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

Then my function is like this:那么我的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;
    }
}

This works when I had $file = fopen($temp_name, 'r');这在我有$file = fopen($temp_name, 'r');时有效but the file uploaded was a weird file.但上传的文件是一个奇怪的文件。

Edit 2编辑 2

This is what the file looks like when the person at the other end of this API tries to open it.这是 API 另一端的人试图打开文件时的样子。

在此处输入图像描述

this is what you want: remove CURLOPT_POSTFIELDS altogether, and replace CURLOPT_CUSTOMREQUEST=>'PUT' with CURLOPT_UPLOAD=>1 and replace 'r' with 'rb' , and use CURLOPT_INFILE (you're supposed to use INFILE instead of POSTFIELDS),这就是您想要的:完全删除 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']
));

This works when I had $file = fopen($temp_name, 'r');这在我有 $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 (and unless you really know what you're doing, you don't want the text mode, ever, unfortunate that it's the default mode), 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 (除非你真的知道你在做什么,否则你永远不想要文本模式,不幸的是它是默认模式),

but the file uploaded was a weird file.但上传的文件是一个奇怪的文件。 (...) This is what the file looks like when the person at the other end of this API tries to open it. (...) 这是 API 另一端的人试图打开文件时的样子。

well you gave CURLOPT_POSTFIELDS a resource.好吧,你给了 CURLOPT_POSTFIELDS 一个资源。 CURLOPT_POSTFIELDS accepts 2 kinds of arguments, #1: an array (for multipart/form-data requests), #2: a string (for when you want to specify the raw post body data), it does not accept resources. CURLOPT_POSTFIELDS 接受 2 种 arguments,#1:一个数组(用于multipart/form-data请求),#2:一个字符串(用于指定原始帖子正文数据时),它不接受资源。

if the php curl api was well designed, you would get an InvalidArgumentException, or a TypeError, when giving CURLOPT_POSTFIELDS a resource.如果 php curl api 设计良好,则在提供 CURLOPT_POSTFIELDS 资源时会收到 InvalidArgumentException 或 TypeError but it's not well designed.但它的设计并不好。 instead, what happened is that curl_setopt implicitly casted your resource to a string, hence resource id #X , it's the same as doing相反,发生的事情是 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