<?php
//文件数据,第一次访问文件
$c=file_get_contents('http://tp4.sinaimg.cn/1692980395/180/1298526784/0');
//文件格式,第二次访问文件。有什么好办法避免吗?
$i=getimagesize('http://head.xiaonei.com/photos/0/0/men_main.gif');
//获取扩展名。有更好的办法从mime类型得到对应扩展名吗?
$e=substr($i[mime],-3,3);
//保存文件
file_put_contents("abc.{$e}",$c);
?>

解决方案 »

  1.   

    先采集图片到本地
    再getimagesize本地图片,获得图片类型,
    再保存 就可以了
      

  2.   


    $url = 'http://tp4.sinaimg.cn/1692980395/180/1298526784/0';
    file_put_contents('tmp.png', file_get_contents($url)) ;
    $arr = getimagesize('tmp.png');
    $filename = time();
    $extname = preg_replace('/(.*)\//','',$arr['mime']); //获取扩展名
    file_put_contents($filename.'.'.$extname, file_get_contents('tmp.png')) ;
      

  3.   


    1、请问你凭什么就认为这个地址是png图片?
    2、即使保存在本地然后再getimagesize本地图片,还是免不了再次读取文件了。没办法直接从图片的字符流直接判断出类型吗?
      

  4.   

    而且 $extname = preg_replace('/(.*)\//','',$arr['mime']); 获取后缀名非常不准确。‘image/jpeg’,得到的后缀是jpeg而不是jpg。
      

  5.   

    因为不知道是什么类型的图片,所以才用tem.png过度的,
    虽然是.png但内容仍然是原来的图片格式。所有后来通过mime获得图片格式,再改扩展名,也没有问题。jpg和jpeg 是扩展名可以通用,不影响浏览。虽然说这样也是二次读文件,但第二次毕竟在本地,速度要快一些。
      

  6.   


    1、本地的二次读取肯定比远程好了不少了,不过我希望的是有没有办法完全就避免二次读取文件?
    2、此例而言jpg和jpeg的区别也不大,但有很多mime类型对应的后缀完全不可使用此方式得到,比如application/mspowerpoint对应*.ppt,有没有更加安全合理的从mime类型到后缀名的办法?
      

  7.   

    只一次读文件的方法,可以用curl,header和body一起获取,分析头部得到图片类型,这个要比mime可靠得多,
    不给出正确的类型,浏览器是无法识别的。然后去除头部,保存文件。仅仅一次读文件,保存。
    代码如下:$url = 'http://tp4.sinaimg.cn/1692980395/180/1298526784/0';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_NOBODY, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $contents = curl_exec($ch);
    curl_close($ch);
    //header("content-type: image/jpeg");
    $filename = time();
    preg_match('/image\/(.*?)\s+/i',$contents,$arr);
    $extname = $arr[1];
    $contents = preg_replace('/HTTP.*close\s+/is','',$contents);
    file_put_contents($filename.'.'.$extname , $contents)兄弟,40分太少了吧,再加40分吧
      

  8.   


    没问题,完美解决的话,加到100分。话说你这里preg_match('/image\/(.*?)\s+/i',$contents,$arr);还是从mimetype拆分字符来获取extension啊,不够安全合理,对于application/mspowerpoint你这样得到的是mspowerpoint,而不是ppt。
      

  9.   

    我说错了,最后这个方式应该是说从content-type到extension,但和mime-type到extension一样,不安全合理。
      

  10.   

    下面这个应该可以了吧,那个数组,你根据自己的需要添加。
    content-type 类型,网上自己搜一搜。$mime = array('image/gif'=>'gif','image/x-xbitmap'=>'bmp','image/x-png'=>'png','image/jpeg'=>'jpg','application/vnd.ms-powerpoint'=>'ppt');
    //当然还有很多的类型,这个根据需要你自己添加。
    $url = 'http://tp4.sinaimg.cn/1692980395/180/1298526784/0';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_NOBODY, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $contents = curl_exec($ch);
    curl_close($ch);$filename = time();
    preg_match('/(image\/(?:.*?))\s+/i',$contents,$arr);
    $key = trim($arr[1]);
    if(array_key_exists($key , $mime)){
      $extname = $mime[$arr[1]] ;
      $contents = preg_replace('/HTTP.*close\s+/is','',$contents);
      file_put_contents($filename.'.'.$extname , $contents)
    }else{
      echo '不在下载范围之列。';
    }
      

  11.   

    $extname = $mime[$arr[1]] ;
    改成
    $extname = $key ;
      

  12.   

    $key = trim($arr[1]);
    改成 
    $key = strtolower(trim($arr[1]));那个数组键值和键名 都要求小写。这样就不会出错了。
      

  13.   


    $mime_types = array(
        'gif' => 'image/gif',
        'jpg' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'jpe' => 'image/jpeg',
        'bmp' => 'image/bmp',
        'png' => 'image/png',
        'tif' => 'image/tiff',
        'tiff' => 'image/tiff',
        'pict' => 'image/x-pict',
        'pic' => 'image/x-pict',
        'pct' => 'image/x-pict',
        'tif' => 'image/tiff',
        'tiff' => 'image/tiff',
        'psd' => 'image/x-photoshop',    'swf' => 'application/x-shockwave-flash',
        'js' => 'application/x-javascrīpt',
        'pdf' => 'application/pdf',
        'ps' => 'application/postscrīpt',
        'eps' => 'application/postscrīpt',
        'ai' => 'application/postscrīpt',
        'wmf' => 'application/x-msmetafile',    'css' => 'text/css',
        'htm' => 'text/html',
        'html' => 'text/html',
        'txt' => 'text/plain',
        'xml' => 'text/xml',
        'wml' => 'text/wml',
        'wbmp' => 'image/vnd.wap.wbmp',    'mid' => 'audio/midi',
        'wav' => 'audio/wav',
        'mp3' => 'audio/mpeg',
        'mp2' => 'audio/mpeg',    'avi' => 'video/x-msvideo',
        'mpeg' => 'video/mpeg',
        'mpg' => 'video/mpeg',
        'qt' => 'video/quicktime',
        'mov' => 'video/quicktime',    'lha' => 'application/x-lha',
        'lzh' => 'application/x-lha',
        'z' => 'application/x-compress',
        'gtar' => 'application/x-gtar',
        'gz' => 'application/x-gzip',
        'gzip' => 'application/x-gzip',
        'tgz' => 'application/x-gzip',
        'tar' => 'application/x-tar',
        'bz2' => 'application/bzip2',
        'zip' => 'application/zip',
        'arj' => 'application/x-arj',
        'rar' => 'application/x-rar-compressed',    'hqx' => 'application/mac-binhex40',
        'sit' => 'application/x-stuffit',
        'bin' => 'application/x-macbinary',    'uu' => 'text/x-uuencode',
        'uue' => 'text/x-uuencode',    'latex'=> 'application/x-latex',
        'ltx' => 'application/x-latex',
        'tcl' => 'application/x-tcl',    'pgp' => 'application/pgp',
        'asc' => 'application/pgp',
        'exe' => 'application/x-msdownload',
        'doc' => 'application/msword',
        'rtf' => 'application/rtf',
        'xls' => 'application/vnd.ms-excel',
        'ppt' => 'application/vnd.ms-powerpoint',
        'mdb' => 'application/x-msaccess',
        'wri' => 'application/x-mswrite',
    );网上找来的。
    想换过来的话,就直接array_flip吧,不过,有些会覆盖(jpeg/jpg都给覆盖成jpe)。
      

  14.   

    只能这样了其实我以为可以有系统函数支持mime-type到extension或者content-type到extension的转换方法。看来没有,还是回到了原点系统有
    image_type_to_extension()
    image_type_to_mime_type()不过这里的"type",却没提供相应的方法获得。
      

  15.   

    因为你要求只读一次文件。就只能用这个方法。如果还要读出文件的属性。那就违背了只读一次的初衷了。注:file_put_contents($filename.'.'.$extname , $contents);//刚才少个分号
      

  16.   


    即便使用多次,也没办法安全的灵活的得到后缀名。比如使用getimagesize,得到的是mime-type。或者你使用curl获取文件,可以取到响应中的content-type。但不论怎样,从mime-type或者content-type到entension,只能是笨拙的定义一个相互对应的数组来得到extension。虽然安全了,但不够灵活。
      

  17.   

    系统没有这个函数,没办法啊。
    不过你可以用c++写个通过二进流获取文件类型的ActiveX插件。这样就既安全又灵活了。