* Download.php

<?php

class Download {

    public static function image($src, $outpath, $contentType) {
        $ch = curl_init();

        $headers = [
            'accept: q=0.9,image/webp,image/apng,*/*;q=0.8',
            'accept-ranges: bytes',
        ];

        curl_setopt_array($ch, [
            CURLOPT_URL => $src,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_HEADER => 0,
            CURLOPT_HTTPHEADER => $headers,
        ]);
        $stream = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);

        ob_start();
        header('Content-Type: '.$contentType);
        file_put_contents($outpath, $stream);
        ob_clean();
        flush();

        return $info;
    }

    private static function getContentTypeByExt($ext) {
        switch ($ext) {
            case 'jpg':
            case 'jpeg': $type = 'image/jpeg'; break;
            case 'png': $type = 'image/png'; break;
            case 'gif': $type = 'image/gif'; break;
            default:
                $type = 'application/octet-stream';
        }
        return $type;
    }

    public static function fileForEachRow(string $path, callable $handler) {
        $file = new SplFileObject($path, "r");
        if (!$file) {
            return -1;
        }
        $n = 0;
        while (!$file->eof()) {
            $line = ltrim($file->fgets(), " \t\n\r\0\x0B");
            $line = rtrim($line, " \t\r\n");
            call_user_func($handler, $line);
            ++$n;
        }
        return $n;
    }

    public static function main() {
        $outdir = "./out";
        is_dir($outdir) || mkdir($outdir, 0755);

        $input = './imagelist.txt';
        $n = self::fileForEachRow($input, function($src) use ($outdir) {
            $src = Path::trimParams($src);
            $filename = Path::basename($src);
            $ext = Path::ext($filename);
            $outpath = $outdir.'/'.$filename;
            $contentType = self::getContentTypeByExt($ext);
            $info = self::image($src, $outpath, $contentType);

            // Rename unexpected file extension
            if (!in_array($ext, ['jpg', 'gif', 'png'])) {
                $ext = Path::basename($info['content_type']);
                $nPath = $outdir.'/'.Path::genFilename($ext);
                rename($outpath, $nPath);
                $outpath = $nPath;
            }
            echo $outpath.PHP_EOL;
        });
        if ($n < 0) {
            printf ("open file %s error\n", $input);
        }
    }
}

function __autoload($className) {
    include $className.'.php';
}

Download::main();

* Path.php

<?php
/**
 * Created by PhpStorm.
 * User: Mch
 * Date: 2019-02-24
 * Time: 16:48
 */

class Path {
    public static function basename($url) {
        return self::suffix($url, '/');
    }

    public static function dirname($path) {
        return self::prefix($path, DIRECTORY_SEPARATOR);
    }

    public static function ext($filename) {
        return self::suffix($filename, '.');
    }

    private static function suffix($str, $sep) {
        $len = strlen($str);
        for ($i = $len-1; $i >= 0; $i--) {
            if ($sep === $str[$i]) {break;}
        }
        return substr($str, $i+1);
    }

    public static function trimParams($url) {
        return self::prefix($url, '?');
    }

    private static function prefix($str, $sep) {
        $len = strlen($str);
        for ($i = 0; $i < $len; $i++) {
            if ($sep === $str[$i]) {break;}
        }
        return substr($str, 0, $i);
    }

    public static function genFilename($ext) {
        return md5(uniqid()).'.'.$ext;
    }
}

* imagelist.txt

https://upload-images.jianshu.io/upload_images/16092054-e14ed4b205b41f70.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640/format/webp
https://t10.baidu.com/it/u=1767691917,3074294217&fm=76
https://t12.baidu.com/it/u=1747711025,3003255952&fm=76
https://f10.baidu.com/it/u=380919057,2388505064&fm=76

* test:

$ php Download.php 

./out/16092054-e14ed4b205b41f70.jpg

./out/2b9b987997ea8c7f197e01a82fb36df2.jpeg

./out/20f0c483701b566d8f43b7e242832d6f.jpeg

./out/24dbf094f8c91af4a126ee9ff1842212.jpeg

----------------------------------------------------------------

curl_getinfo() 返回关联数组 size_download,下载文件大小

@ref:

/**
 * Get information regarding a specific transfer
 * @link https://php.net/manual/en/function.curl-getinfo.php
 * @param resource $ch 
 * @param int $opt [optional] <p>
 * This may be one of the following constants:
 * CURLINFO_EFFECTIVE_URL - Last effective URL
 * @return mixed If opt is given, returns its value as a string.
 * Otherwise, returns an associative array with the following elements 
 * (which correspond to opt):
 * "url"
 * "content_type"
 * "http_code"
 * "header_size"
 * "request_size"
 * "filetime"
 * "ssl_verify_result"
 * "redirect_count"
 * "total_time"
 * "namelookup_time"
 * "connect_time"
 * "pretransfer_time"
 * "size_upload"
 * "size_download"
 * "speed_download"
 * "speed_upload"
 * "download_content_length"
 * "upload_content_length"
 * "starttransfer_time"
 * "redirect_time"
 * @since 4.0.4
 * @since 5.0
 */
function curl_getinfo ($ch, $opt = null) {}