buaazp / zimg

A lightweight and high performance image storage and processing system.
http://zimg.buaa.us
BSD 3-Clause "New" or "Revised" License
2.69k stars 402 forks source link

`fail post type` When trying to post file to zimg from PHP(HHVM 3.8.0) #97

Closed r3wt closed 9 years ago

r3wt commented 9 years ago

the message it says in the console window of ZIMG: 2015/08/04 08:09:44:032706 [ERROR] <SERVER IP> fail post type

the message it says from the response of CURL:

File type not support.

My code:


if( !is_uploaded_file($_FILES[$img_name]['tmp_name']) ){
    throw new \exception('bad file input');
}

$type = finfo_file(finfo_open(FILEINFO_MIME_TYPE),$image_temp);

if( !in_array($etype,$exif) || !in_array($type,$finfo)){
    throw new \exception('file type not allowed');
}

switch($type){
    case 'image/gif':
        $type2 = 'gif'; //get the type so we can know for zimg and tell it
    break;
    case 'image/png':
        $type2 = 'png';
    break;
    case 'image/jpeg':
    case 'image/jpg':
    case 'image/pjpeg':
        $type2 = 'jpeg';
    break;
}

$ch = curl_init($args['img_url'].'upload'); //path to zimg + upload path.

curl_setopt($ch,CURLOPT_HTTPHEADER, ['Content-Type: '.$type2]); //set content type as explained in zimg GuideBook

curl_setopt($ch,CURLOPT_POST,1); //specify raw post ways.

curl_setopt($ch,CURLOPT_POSTFIELDS, [
    'userfile' => new \CURLFile($image_temp,$type,'userfile') //attach file in raw post way
]);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = json_decode(curl_exec($ch),true); //get result
curl_close($ch);

if($result['ret'] == false){
    throw new \exception($result['error']['message']); // if exception occurred in zimg unwind stack and output error
}

$app->session['user']->update_avatar($result['info']['md5']); //sync the model with the new image

Now it is not immediately clear why it is failing, as the documentation don't say. I have examined the $type2 variable and it clearly says png for the image i am testing, which is defined in allowed type:

allowed_type    = {'jpeg', 'jpg', 'png', 'gif', 'webp'}

What am i doing wrong here?

I have tried with both localhost and fqdn, but no success.

buaazp commented 9 years ago

I'm not sure what php-curl do when it send post request because I don't use php ever. I guess the reason is header doesn't match what you want. So try this modify:

curl_setopt($ch,CURLOPT_HTTPHEADER, ['Content-Type: '.$type2]);

to

curl_setopt($ch,CURLOPT_HTTPHEADER, ['Content-Type:'.$type2]);

remove the blank space. Maybe it will work.

If this doesn't work, here is a zimg user's php code example, you can have a look.

$zimg_upload_url = 'http://fanrong33.com:4869/upload';

// 存储图片到本地
$remote_file = 'http://gd2.alicdn.com/bao/uploaded/i2/T1OxmwFP4bXXXXXXXX_!!0-item_pic.jpg';
Log::write('collect picture to zimg, image_file:'.$remote_file, Log::INFO);
$ext = get_file_ext($remote_file);

$dir = 'article';
$save_path = 'uploads/'.$dir.'/'.date('Y').'/'.date('md').'/';
$save_rule = md5(uniqid(mt_rand(), true));

if(!is_dir($save_path)){
    if(false === mkdir($save_path, 0700, true)){
        exit('创建目录失败');
    }
}
$save_image_file = $save_path.$save_rule.".$ext";

$bytes = file_put_contents($save_image_file, file_get_contents($remote_file));
///////////////////////////////
// 返回存储到服务器的真实图片地址
$realpath = realpath($save_image_file);

// 上传图片到zimg图片存储服务
$ch = curl_init();

$post_data = file_get_contents($realpath); // raw_post方式
$headers = array();
$headers[] = 'Content-Type:'.$ext; // 还有这里!

curl_setopt($ch, CURLOPT_URL, $zimg_upload_url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);  
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

$info = curl_exec($ch);
curl_close($ch);

$json = json_decode($info, true);
$signature = $json['info']['md5'];
buaazp commented 9 years ago

refer to #45

r3wt commented 9 years ago

Hi, the culprit seems to be CURLFile. when i try with file get contents instead, i get permission error from zimg. now i think if ican try t start zimg with different user it should work. thank you for your help.

img

r3wt commented 9 years ago

Ok, i got past the problem and it say i uploaded the file, but now it is this error when trying to view image: 404 Not Found!

buaazp commented 9 years ago

The reason of upload succ but get failed maybe imagemagick processing failed. You can find the error details in log.

r3wt commented 9 years ago

I don't know. repeating the upload a subsequent time, the error seems resolved. i thank you for the very great image storage system, and i will not waste any more of your time.

edit and now it happens again. unknown why

r3wt commented 9 years ago

I found the issue, and it is unfortunate. it appears zimg use a md5 of the file to name image, not accounting for permutations. so this removes my ability to delete previously stored image when user change profile picture. i think this is an unfortunate design choice for zimg, since it removes ability for reliable automated removal of images. i find it curious that the design doesn't account for the permutations of images, so this lead to storage bloat with unnecessary files.

public function update_avatar($avatar)
{
    $app = \StarterKit\App::getInstance();
    if(!empty($this->avatar)){
        //if i send this request to delete the users previously stored avatar, and the
        //new avatar is same md5, then bug happens that user has no picture.
        $app->get_request($app->args['img_url'].'admin?md5='. $this->avatar .'&t=1');
    }
    $this->avatar = $avatar;
    $db = $app->db;
    $model = $db->model('user',$this->id);
    $db->updateColumn($model,'avatar',$this->avatar);
    return true;
}