使用Curl PHP将图像上传到Imgur

时间:2017-07-22 15:35:32

标签: php curl imgur

<form action="php.php" method="post" enctype="multipart/form-data">
  Send these files:<br />
  <input name="img[]" type="file" multiple="multiple" /><br />
  <input type="submit" value="Send files" />
</form>
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
foreach ($_FILES['img']['tmp_name'] as $index => $tmpName) {
    if( !empty( $tmpName ) && is_uploaded_file( $tmpName ) )
    {
        $handle = fopen($tmpName, "r");
        $data = fread($handle, filesize($tmpName));
        $client_id = "d5f419ef9aedf16";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://api.imgur.com/3/image.json');
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Client-ID ' . $client_id));
        curl_setopt($ch, CURLOPT_POSTFIELDS, array('image' => base64_encode($data)));
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        curl_setopt($ch, CURLOPT_STDERR, fopen('php://stderr', 'w'));

        $reply = curl_exec($ch);
        $info = curl_getinfo($ch);
        var_dump($info);
        if(curl_errno($ch))
            echo 'Curl error: '.curl_error($ch);
        curl_close($ch);
        $reply = json_decode($reply);
        printf('<img height="180" src="%s" >', $reply->data->link);
    }
}
?>

我创建了这个页面,在localhost上完美运行但是当我从服务器运行它时它不起作用,问题是我根本没有输出,甚至没有curl_getinfo或错误。不知道如何调试这个,因为我无法获得任何信息。

3 个答案:

答案 0 :(得分:0)

你做错了几件事。

此代码: 即使在没有文件的GET请求中也会执行foreach ($_FILES['img']['tmp_name'] as $index => $tmpName) {,因此$_FILES['img']不存在,并且您收到Undefined index: img错误。此外,在GET请求中,这个未定义的索引错误会返回NULL给foreach,当你告诉foreach()循环NULL时,它会给你这个错误:Invalid argument supplied for foreach()。你还没有意识到这一点,证明你没有检查php错误日志。这是调试故障php脚本时应该做的第一件事。 - 修复这两个问题,将foreach包装在if(!empty($_FILES['img']['tmp_name']){}中 - 接下来,找到PHP错误日志,并阅读这些错误报告。 (通常你可以在error_log下的phpinfo()中找到它 - 或者它的emptystring,它的你的web服务器&#39;错误日志,例如对于nginx有一个空的php error_log php设置,它在nginx&#39;错误日志(如/var/log/nginx/error.log)

下一期,$handle = fopen($tmpName, "r");这将破坏某些系统(着名的是Windows)上的二进制数据(如图像),将其更改为rb以安全读取二进制数据(图像格式为二进制)< / p>

下一期,您认为fread()会读取您请求读取的字节数,这是不正确的。 fread将读取UP TO所请求的字节数,但在读取所请求的字节数之前可能会因多种原因而停止。你要么必须循环调用fread直到它已经读取了所有字节,或者更好的是,使用stream_get_contents,这将基本上为你执行fread()循环。

下一期,这一行curl_setopt($ch, CURLOPT_STDERR, fopen('php://stderr', 'w'));完全没必要,PHP的STDERR无论如何都是libcurl的默认STDERR。

下一期,你不要fclose()$ handle。这对于短脚本运行脚本来说是可以的(因为脚本完成时你的操作系统fclose()),但是你的代码越大,资源泄漏的时间越长,它总是关闭它的编程习惯,所以那样做。

下一期,我不能相信imgur实际上想要一个base64编码的图像副本,就是这样一个cpu&amp;带宽和ram waste ...他们正在使用的POST编码,multipart/form-data是完全二进制安全的,因此没有理由对它进行base64编码...你确定他们想要base64编码吗?你和他们可以通过不使用base64编码来节省大约33%的带宽。

鉴于你在文件操作中所做的所有事情,最好使用file_get_contents函数 - 它读取整个文件,它以二进制读取模式打开文件(相反)到您的代码,在TEXT模式下打开它,在读取时可能会破坏图像),它会读取整个文件,而不仅仅是第一个fread()调用将读取的块(如果你&# 39;幸运的是,整个文件,但如果你不幸运,只是它的第一块),它会为你做fclose()(你忘了做)

答案 1 :(得分:0)

感谢hans的建议,你是对的,使用base64不是强制性的,不是在V3 API中,它是以前的版本,不再是。现在它要快得多。这是我的最终代码

if(!empty($_FILES['img']['tmp_name'])){
    foreach ($_FILES['img']['tmp_name'] as $index => $tmpName) {
        if( !empty( $tmpName ) && is_uploaded_file( $tmpName ) )
        {
            if ($handle = fopen($tmpName, "rb")) {
                $data = stream_get_contents($handle, filesize($tmpName));
                $client_id = "d5f619ef9aedf16";
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, 'https://api.imgur.com/3/image.json');
                curl_setopt($ch, CURLOPT_POST, TRUE);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Client-ID ' . $client_id));
                curl_setopt($ch, CURLOPT_POSTFIELDS, array('image' => $data));
                curl_setopt($ch, CURLOPT_VERBOSE, true);
                $reply = curl_exec($ch);
                if(curl_errno($ch))
                    echo 'Curl error: '.curl_error($ch);
                curl_close($ch);
                $reply = json_decode($reply);
                $screens .= $reply->data->link . " ";
                fclose($handle);
            }
        }
    }
}

没有上传图片的原因是upload_max_filesize和max_post_size,我已经增加了它们,我没有遇到任何问题。

答案 2 :(得分:0)

为什么不使用imgur php sdk并通过以下代码简单地实现它:

require_once APPPATH."/third_party/imgur/vendor/autoload.php";


    $pathToFile = '../path/to/file.jpg';
    $imageData = [
        'image' => $pathToFile,
        'type'  => 'file',
    ];

    $client->api('image')->upload($imageData);