用php渲染图像

时间:2015-06-17 14:28:53

标签: php image laravel image-processing

为了简单起见,我尝试使用php显示图像以帮助尝试并防止任何类型的安全漏洞。我通过php脚本读取图像并且我想要呈现它,所以不要去http://example.com/path/to/uploads/dir/image.jpg我想让用户能够转到http://example.com/path/to/script/image1并让他们能够看到图像。

这样我就可以隐藏文档根目录之外的图像路径(http://example.com/path/to/uploads/dir/)(域路径无法直接访问它)。因此,如果域名的路径为/path/to/public_html/,那么我希望将图片上传到/path/to/uploads/,以便您在浏览我的域时无法导航到上传目录。

我的问题是我尝试渲染的图像,不会渲染,我不确定为什么。 MD5校验和是相同的,HTTP标头是相似的。图像的direct path与图像的desired path相比较。

我使用Laravel作为框架/主干,但我认为这不重要,我的代码渲染图像在

之下
public function getImage($id){
  $img = TitanImage::findOrFail($id);
//  header('Content-type: image/jpeg');
//  header('Content-Length: ' . filesize($img->path));
//  header('Accept-Ranges: bytes');
//  echo file_get_contents($img->path);
  $file = $img->path;
  $type = 'image/jpeg';
  header('Content-Type:'.$type);
  header('Content-Length: ' . filesize($file));
  readfile($file);
//  exit();
  return;
}

我还使用webconfs来检查两个所需图像端点的标头。

编辑1

关于intervention/image包的一条评论,我改变了我的代码,但仍然得到了相同的结果;然而,内容长度已经改变,它变得更长。

public function getImage($id){
  $img = TitanImage::findOrFail($id);
//  header('Content-type: image/jpeg');
//  header('Content-Length: ' . filesize($img->path));
//  header('Accept-Ranges: bytes');
  $file = $img->path;
  return Image::make(trim($file,' '))->response();
}

编辑2

在此编辑中,@ Digitlimit提到检查图像是否存在。这是我目前的代码。

public function getImage($id){
  $img = TitanImage::findOrFail($id);
  $file = $img->path;
  if(file_exists($file))
    return Image::make($file)->response('jpg');
  else
    return 'File doesnt exist';
}

我还测试了如果我只是返回$file而不是Image::make实例会发生什么,我得到了正确的路径,即。当我进入服务器的SSH和cd到路径减去图像名称时,路径存在并具有权限。当我执行ls -la命令时,它会列出图像,并且它还具有适当的权限。

2 个答案:

答案 0 :(得分:2)

代码正在运行 - 问题是它发送了额外的信息。文件 ,找到 ,发送 。返回图片的链接:

HTTP/1.1 200 OK
Date: Wed, 17 Jun 2015 22:52:03 GMT
Server: Apache
Connection: close
Content-Type: image/jpeg

但后续输出错误

00000050  3a 20 63 6c 6f 73 65 0d  0a 43 6f 6e 74 65 6e 74  |: close..Content|
00000060  2d 54 79 70 65 3a 20 69  6d 61 67 65 2f 6a 70 65  |-Type: image/jpe|
00000070  67 0d 0a 0d 0a 20 ff d8  ff e1 19 57 45 78 69 66  |g.... .....WExif|
                         ^^
                           `this 20 here, before the ff d8 ff of JPEG.

所以这段代码(只负责JPEG部分)是可以的。

public function getImage($id){
  $img    = TitanImage::findOrFail($id);
  $file   = $img->path;
  if (file_exists($file)) {
      return Image::make($file)->response('jpg');
  }
  else {
    return "File doesn't exist";
  }
}

数据流开头的额外空间可能来自某个PHP文件,在开始<?php标记之前有一个额外的空格,或者可能在结束标记之后。

对于后者,建议您关闭<?php标记,即您从不包含“?&gt;”序列

对于前者,请尝试

public function getImage($id) {
    return "*** is there a space before the asterisks?";
}

并观察返回的HTML。除非错误出现在TitanImage中,我认为不太可能,你应该在JPEG图像之前发送的星号之前看到相同的空格。定义getImage()函数的文件可能是可疑的。

否则,您可以运行“grep”来查找 not <?php开头的PHP文件。您可以通过将-v标记添加到grep来修改此shameless plug

答案 1 :(得分:0)

如果您已安装干预图像,请执行以下操作:

public function getImage($id){
  $img = TitanImage::findOrFail($id);
  $file = $img->path;
  return Image::make($file)->response('jpg');
}

编辑: 我在我的项目中对此进行了测试,结果非常好:

<强>路线:

Route::get('/api/v1/titan/image/{id}',function($id){
    return \Image::make(storage_path("/images/$id.jpg"))->response('jpg');
});

项目中的图片位置:

enter image description here

访问网址时的输出: http://laravel.dev/api/v1/titan/image/1

enter image description here

Chrome元素检查 enter image description here

enter image description here