使用 php 获取要渲染的图像

Getting an image to render with php

为简单起见,我尝试使用 php 显示图像以帮助 try 并防止任何类型的安全漏洞。我通过 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 headers 类似。将direct path to the image, compared to the desired path转为图像。

我正在使用 Laravel 作为框架/backbone,但我认为这并不重要,我渲染图像的代码如下

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 检查了两个所需图像端点的 headers。

编辑 1

关于 intervention/image 包的评论之一,我更改了我的代码,但仍然得到相同的结果;但是,content-length 发生了变化,变长了。

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';
}

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

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

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');
});

我项目中的图片位置:

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

Chrome 元素检查

代码正在运行 - 问题是它正在发送 额外 信息。文件 在那里, 找到, 正在发送。 link 到你的图片 returns:

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部分)就OK了。

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";
  }
}

数据流开头的额外 space 可能 来自某些 PHP 文件,在 space 之前有一个额外的白色 space打开 <?php 标签,或者可能在结束标签之后。

对于后者,建议您不要关闭<?php标签,即永远不要包含“?>”序列。

对于前者,试试

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

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

否则,您可以运行 "grep" 查找 PHP 个 而非 <?php 开头的文件。您可以通过将 -v 标志添加到 grep.

来修改此 shameless plug