16

我想知道如何在没有任何模板的情况下从控制器返回图像。我想将它用于时事通讯中的像素跟踪。

我从这段代码开始

    $image = "1px.png";
    $file =    readfile("/path/to/my/image/1px.png");
    $headers = array(
        'Content-Type'     => 'image/png',
        'Content-Disposition' => 'inline; filename="'.$file.'"');
    return new Response($image, 200, $headers);

但是在导航器上,我的链接断开了(找不到文件...)

4

6 回答 6

33

根据提供文件时的 Symfony 文档,您可以使用BinaryFileResponse

use Symfony\Component\HttpFoundation\BinaryFileResponse;
$file = 'path/to/file.txt';
$response = new BinaryFileResponse($file);
// you can modify headers here, before returning
return $response;

此 BinaryFileResponse 自动处理一些 HTTP 请求标头,并使您免于使用readfile()或其他文件功能。

于 2015-11-25T14:27:16.730 回答
10

现在,您将文件名作为响应正文返回,并将文件内容写入 Content-Disposition 的文件名属性。

return new Response($image, 200, $headers);

应该:

return new Response($file, 200, $headers);

... 和 ...

'Content-Disposition' => 'inline; filename="'.$file.'"');

应该 ...

'Content-Disposition' => 'inline; filename="'.$image.'"');

正确的?

进一步看看这个问题

于 2013-07-01T16:31:40.557 回答
5

这对我来说很好。

$filepath = "/path/to/my/image/chart.png";
$filename = "chart.png";

$response = new Response();
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_INLINE, $filename);
$response->headers->set('Content-Disposition', $disposition);
$response->headers->set('Content-Type', 'image/png');
$response->setContent(file_get_contents($filepath));

return $response;
于 2016-03-23T21:54:33.583 回答
3

file_get_contents 是个坏主意。通过 file_get_contents 读取大量图像杀死了我的小服务器。我必须找到另一种解决方案,现在这对我来说非常完美且非常快速。

关键是使用 readfile($sFileName) 而不是 file_get_contents。Symfony 流响应能够接受一个回调函数,该函数将在发送时执行 ($oResponse->send())。所以这是使用 readfile() 的好地方。

作为一个小好处,我写了一种缓存方式。

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ImageController
{

    public function indexAction(Request $oRequest, Response $oResponse)
    {
        // Get the filename from the request 
        // e.g. $oRequest->get("imagename")
        $sFileName = "/images_directory/demoimage.jpg";
        if( ! is_file($sFileName)){
            $oResponse->setStatusCode(404);

            return $oResponse;
        }

        // Caching...
        $sLastModified = filemtime($sFileName);
        $sEtag = md5_file($sFileName);

        $sFileSize = filesize($sFileName);
        $aInfo = getimagesize($sFileName);

        if(in_array($sEtag, $oRequest->getETags()) || $oRequest->headers->get('If-Modified-Since') === gmdate("D, d M Y H:i:s", $sLastModified)." GMT" ){
            $oResponse->headers->set("Content-Type", $aInfo['mime']);
            $oResponse->headers->set("Last-Modified", gmdate("D, d M Y H:i:s", $sLastModified)." GMT");
            $oResponse->setETag($sEtag);
            $oResponse->setPublic();
            $oResponse->setStatusCode(304);

            return $oResponse;
        }

        $oStreamResponse = new StreamedResponse();
        $oStreamResponse->headers->set("Content-Type", $aInfo['mime']);
        $oStreamResponse->headers->set("Content-Length", $sFileSize);
        $oStreamResponse->headers->set("ETag", $sEtag);
        $oStreamResponse->headers->set("Last-Modified", gmdate("D, d M Y H:i:s", $sLastModified)." GMT");

        $oStreamResponse->setCallback(function() use ($sFileName) {
            readfile($sFileName);
        });

        return $oStreamResponse;
    }
}
于 2016-03-12T14:28:41.583 回答
3

快速应答器

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

class AnotherController extends Controller {

  public function imagesAction($img = 'my_pixel_tracking.png'){

    $filepath = '/path/to/images/'.$img;

      if(file_exists($filepath)){
        $response = new Response();
        $disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_INLINE, $img);
        $response->headers->set('Content-Disposition', $disposition);
        $response->headers->set('Content-Type', 'image/png');
        $response->setContent(file_get_contents($filepath));
        return $response;
      }
      else{
        return $this->redirect($this->generateUrl('my_url_to_site_index'));
      }
  }
}
于 2016-11-15T11:02:36.917 回答
2

另外,我不得不改变:

$file =    readfile("/path/to/my/image/1px.png");

对此:

$file =    file_get_contents("/path/to/my/image/1px.png");

似乎 readfile 正在回显内容,因为它读取它强制标头提前输出并否定强制的 Content-Type 标头。

于 2015-10-09T13:59:51.863 回答