テンプレートなしでコントローラーから画像を返す方法を教えてください。ニュースレターのピクセル追跡に使用したいと思います。
私はこのコードから始めます
$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);
しかし、ナビゲーターに壊れたリンクがあります(ファイルが見つかりません...)
現在、ファイル名を応答本文として返し、ファイルコンテンツをContent-Dispositionのファイル名プロパティに書き込みます。
return new Response($image, 200, $headers);
でなければなりません:
return new Response($file, 200, $headers);
...と...
'Content-Disposition' => 'inline; filename="'.$file.'"');
する必要があります...
'Content-Disposition' => 'inline; filename="'.$image.'"');
正しい?
さらに この質問 を見てください。
Symfony Docsによると serving files -- 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()
または他のファイル関数を使用しないようにします。
これは私にとってはうまくいきます。
$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;
また、私は変更する必要がありました:
$file = readfile("/path/to/my/image/1px.png");
これに:
$file = file_get_contents("/path/to/my/image/1px.png");
Readfileは、ヘッダーを早期に出力するように強制し、強制されたContent-Typeヘッダーを無効にするため、内容をエコーしているように見えました。
クイックアンサー
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'));
}
}
}
file_get_contentsはお勧めできません。 file_get_contentsを介して画像の大きなリストを読み取ると、小さなサーバーが停止しました。私は別の解決策を見つけなければなりませんでしたが、これは今では完璧で非常に高速に機能します。
重要なのは、file_get_contentsの代わりにreadfile($ sFileName)を使用することです。 Symfony Stream Responseは、送信中に実行されるコールバック関数を取ることができます($ 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;
}
}