Imagick - 无法从URL读取图像文件。

6

我正在使用这段代码来读取不同网站上的图片:

$image = new Imagick('http://lp.hm.com/hmprod?set=key[source],value[/model/2012/P01 05156 06204 80 1175 4.jpg]&set=key[rotate],value[]&set=key[width],value[]&set=key[height],value[]&set=key[x],value[]&set=key[y],value[]&set=key[type],value[STILL_LIFE_FRONT]&call=url[file:/product/large]');

但是有时候,我会遇到这样一个错误(大约20%的概率):
ImagickException

Unable to read the file: http://lp.hm.com/hmprod?set=key[source],value[/model/2012/P01 05156 06204 80 1175 4.jpg]&set=key[rotate],value[]&set=key[width],value[]&set=key[height],value[]&set=key[x],value[]&set=key[y],value[]&set=key[type],value[STILL_LIFE_FRONT]&call=url[file:/product/large]

Imagick->__construct()

这个错误在整个域名中似乎是一致的,但有时在同一域名下的不同图片上会有所不同。

问题

为什么这是一个问题?
我们应该如何解决它?
是否有其他解决方案?


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - superhero
4个回答

14

步骤 1 :获取 URL

$url = 'http://blablabla.com/blabla.jpeg';

步骤2:将博客内容保存到变量中

$image = file_get_contents($url);

第三步:创建 Imagick 对象

$img = new Imagick();

步骤4:指示imagick对象读取图像的blob内容

$img -> readImageBlob($image);

步骤 5:保存图片(或进行操作)

$img -> writeImage('/var/www/html/uploads/img.jpg');

步骤6:销毁imagick实例

$img -> destroy();

这个不适用于以下url: "http://lp.hm.com/hmprod?set=key[source],value[/model/2012/P01 05156 06204 80 1175 4.jpg]&set=key[rotate],value[]&set=key[width],value[]&set=key[height],value[]&set=key[x],value[]&set=key[y],value[]&set=key[type],value[STILL_LIFE_FRONT]&call=url[file:/product/large]" 这就是问题所在。问题是Imagick无法处理此URI格式。 - superhero
这是一个程序相关的内容,无法翻译成中文。它包含了一段链接和一张图片。 - Uday Hiwarale

1
所以我发现我需要正确编码URL。我不确定这段代码是否最优,但它可以工作...并且有望帮助其他人。
$parsedUrl = parse_url('http://lp.hm.com/hmprod?set=key[source],value[/model/2012/P01 05156 06204 80 1175 4.jpg]&set=key[rotate],value[]&set=key[width],value[]&set=key[height],value[]&set=key[x],value[]&set=key[y],value[]&set=key[type],value[STILL_LIFE_FRONT]&call=url[file:/product/large]');
$info      = pathinfo($parsedUrl['path']);
$dirname   = explode('/', $info['dirname'] ?: '');
$dirname   = array_filter($dirname, 'strlen');
$dirname   = array_map('urlencode', $dirname);
$dirname   = implode('/', $dirname);
$basename  = urlencode($info['basename'] ?: '');
$path      = array_filter(array($dirname, $basename), 'strlen');
$path      = '/' . implode('/', $path);

$query = explode('&', $parsedUrl['query'] ?: '');
foreach ($query as &$set)
{
  $set = explode('=', $set, 2);
  $set = array_map('urlencode', $set);
  $set = implode('=', $set);
}

$query    = implode('&', $query);
      
$uri      = array_filter(array($path, $query), 'strlen');
$uri      = implode('?', $uri);

$fragment = urlencode($info['fragment'] ?: '');
$uri      = array_filter(array($uri, $fragment), 'strlen');
$uri      = implode('#', $uri);

$scheme   = $parsedUrl['scheme'] ?: '';
$host     = $parsedUrl['host']   ?: '';
$url      = array_filter(array($scheme, $host), 'strlen');
$url      = implode('://', $url);
$url     .= $uri;

$image    = new Imagick($url);

注意!

此代码将留下通知。


0
尝试使用urlencode函数对URL中的特殊字符进行编码:
$image = new Imagick(urlencode('http://lp.hm.com/hmprod?set=key[source],value[/model/2012/P01 05156 06204 80 1175 4.jpg]&set=key[rotate],value[]&set=key[width],value[]&set=key[height],value[]&set=key[x],value[]&set=key[y],value[]&set=key[type],value[STILL_LIFE_FRONT]&call=url[file:/product/large]'));

或者如果不行,试试这个:

$content = file_get_contents(urlencode('http://lp.hm.com/hmprod?set=key[source],value[/model/2012/P01 05156 06204 80 1175 4.jpg]&set=key[rotate],value[]&set=key[width],value[]&set=key[height],value[]&set=key[x],value[]&set=key[y],value[]&set=key[type],value[STILL_LIFE_FRONT]&call=url[file:/product/large]'));
$image = new Imagick($content);

不,我已经尝试过了。它会出现新的错误,甚至无法理解URL。我想在这种情况下应该做的是将URL的每个部分拆分并以某种方式对所有不同的部分进行编码。 - superhero
第一条评论只涉及 ´urlencode´。但我也会尝试使用 ´file_get_contents´ 替代方案。 - superhero

0
我刚遇到了类似的问题。我正在使用file_get_contents(),并且得到了相同的“ImagickException文件名太长”的错误。对我来说,解决方法是找到tmp目录并为其设置正确的权限。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接