【问题标题】:Return Image from Controller symfony2从控制器 symfony2 返回图像
【发布时间】:2013-07-01 16:18:08
【问题描述】:

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

我从这段代码开始

    $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);

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

【问题讨论】:

标签: symfony controller response


【解决方案1】:

根据 serving files 时的 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() 或其他文件函数。

【讨论】:

  • 这不适用于动态创建的图像数据。
【解决方案2】:

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

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

应该是:

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

...和...

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

应该是……

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

对吗?

进一步看看this question

【讨论】:

  • 完美!解决方案是另一个话题。在你的情况下,我有一个 500 错误代码。谢谢你的链接
【解决方案3】:

这对我来说很好。

$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;

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      快速回答

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

      【讨论】:

        【解决方案6】:

        另外,我必须改变:

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

        到这里:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-28
          • 2014-01-26
          • 2016-02-29
          • 2012-09-22
          • 2016-11-19
          • 2020-02-18
          • 2015-10-15
          相关资源
          最近更新 更多