通过curl上传后文件损坏

时间:2016-12-07 00:44:48

标签: php rest curl file-upload php-7

我想上传图片文件。 Target是具有oAuth2自动化的REST api端点。我设法上传了一些东西但是当我在服务器上打开文件时它已经损坏了。大小与源文件不匹配。

这是我使用的代码:

<?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数组是空的,这就是我手动创建整个请求体的原因。

2 个答案:

答案 0 :(得分:1)

过了一段时间,我成功地完成了这项工作:

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

现在文件在服务器端可见并且它没有损坏,但这仍然无法回答为什么&#34;正常&#34;不行的方式。如果有人能解释这里发生了什么,那就太好了。)

答案 1 :(得分:0)

来自curlopt_postfields的{​​{3}}:

  

要发布文件,请在文件前加上@并使用完整路径。该   filetype可以通过跟随文件名显式指定   格式'; type = mimetype'的类型。此参数可以是   作为urlencoded字符串传递,如'para1 = val1&amp; para2 = val2&amp; ...'或作为   一个数组,字段名称为键,字段数据为值。如果有价值   是一个数组,Content-Type标头将设置为   多部分/格式的数据。从PHP 5.2.0开始,如果是文件,则值必须是数组   使用@前缀传递给此选项。从PHP 5.5.0开始,@   不推荐使用prefix,可以使用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);