2016-12-07 48 views
2

我想上传图像文件。目标是具有oAuth2自动化功能的REST API端点。我设法上传的东西,但是当我打开服务器上的文件已损坏。大小与源文件不匹配。上传通过curl后损坏的文件

这是我使用的代码:

<?php 
$file = 'example.jpg'; 

$finfo = finfo_open(FILEINFO_MIME_TYPE); 
$finfo = finfo_file($finfo, __DIR__.'/'.$file); 

$ending = "\r\n"; 

$boundary = md5(microtime()); 
$fullBoundary = sprintf("--%s%s", $boundary, $ending); 

$body = ''; 
$body .= $fullBoundary; 
$body .= "Content-Disposition: form-data; name=\"image\"; filename=\"$file\"".$ending; 
$body .= "Content-Type: $finfo".$ending; 
$body .= "Content-Transfer-Encoding: base64".$ending.$ending; 
$body .= chunk_split(base64_encode(file_get_contents(__DIR__.'/'.$file))).$ending; 
$body .= "--".$boundary."--".$ending.$ending; 
$ch = curl_init(); 
curl_setopt(
    $ch, 
    CURLOPT_HTTPHEADER, 
    [ 
     'Authorization: Bearer token...', 
     "Content-Type: multipart/form-data; boundary=".$boundary, 
    ] 
); 
curl_setopt($ch, CURLOPT_URL, "http://api.example.com/upload"); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLINFO_HEADER_OUT, true); 
curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_POST, true); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $body); 
curl_setopt($ch, CURLOPT_VERBOSE, true); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); 
$curl_response = curl_exec($ch); 
print_r(curl_getinfo($ch)); 
print_r($curl_response); 
curl_close($ch); 

谁能帮助我吗?

P.S.我忘记说我试过使用“@”符号和\ CurlFile,但后来$ _FILES数组是空的,这就是为什么我手动创建了整个请求体。

回答

0

PHP manualcurlopt_postfields

要发布一个文件,在前面加上@文件名,并使用完整路径。 文件类型可以通过跟随 格式'; type = mimetype'格式的文件名来显式指定。此参数可以是 作为urlencoded字符串传递,如'para1 = val1 & para2 = val2 & ...'或 以字段名称作为键和字段数据作为值的数组。如果值 是一个数组,则Content-Type标题将被设置为 multipart/form-data。从PHP 5.2.0开始,如果使用@前缀将文件 传递给此选项,则值必须是数组。从PHP 5.5.0开始,@ 前缀已被弃用,并且可以使用CURLFile发送文件。 @ 前缀可以被禁用,以安全地传递以@开头的值 将CURLOPT_SAFE_UPLOAD选项设置为TRUE。

尝试像这样发送文件。

$file = 'example.jpg'; 
$finfo = finfo_open(FILEINFO_MIME_TYPE); 
$finfo = finfo_file($finfo, __DIR__.'/'.$file); 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_POSTFIELDS, array('file' => '@'.realpath($file).';filename='.basename($file).';type='.$finfo)); 
curl_setopt(
    $ch, 
    CURLOPT_HTTPHEADER, 
    [ 
     'Authorization: Bearer token...', 
     "Content-Type: multipart/form-data; boundary=".$boundary, 
    ] 
); 
curl_setopt($ch, CURLOPT_URL, "http://api.example.com/upload"); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLINFO_HEADER_OUT, true); 
curl_setopt($ch, CURLOPT_HEADER, true); 
curl_setopt($ch, CURLOPT_POST, true); 
curl_setopt($ch, CURLOPT_VERBOSE, true); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); 
$curl_response = curl_exec($ch); 
print_r(curl_getinfo($ch)); 
print_r($curl_response); 
curl_close($ch); 
+0

对不起,在问题中没有提及它,我使用PHP 7.1,据我所知,这个符号不再被支持。我试过\ CurlFile但是然后$ _FILES数组在服务器端是空的 – Vail

+0

@Vail你有什么证据来支持这个理论。如果它在7中被弃用,那么文档会注意到它,他们没有。这是如何完成的。 –

+0

嗯,我找不到我读的地方,这个表示法在PHP7中不起作用,但它绝对不推荐使用。即使在上面粘贴的片段中,他们也提到了它:“从PHP 5.5.0开始,@前缀被弃用,并且文件可以使用CURLFile发送。可以禁止@前缀通过设置CURLOPT_SAFE_UPLOAD选项来安全传递值为@的值为真“。 – Vail

1

一段时间后,我设法与这本作品:

$body .= "Content-Transfer-Encoding: multipart/form-data".$ending.$ending; 
$body .= file_get_contents(__DIR__.'/'.$file).$ending; 

现在的文件是在服务器端可见,并且它没有损坏,但是这仍然没有回答为什么“正常”的方式唐没有工作。如果有人能解释这里发生了什么,这将是非常好的:)