在 symfony 中使用 blob 图像的图像库

发布于 2024-10-11 15:15:52 字数 118 浏览 5 评论 0原文

我的数据库表中有一个作为 blob 的图像列表。

我想做的是显示 listSuccess.php 中的图像,就像画廊一样。

有人可以提供一些可以帮助或让我开始的代码吗?

问候

I have a list of images as blobs in my database table.

What I'd like to do is display the images in listSuccess.php, like a gallery.

Could someone provide some code that would help or get me started?

Regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓬勃野心 2024-10-18 15:15:52

首先,如果将数据存储在数据库中,请勿将其存储在单个表中。
这是我的示例:

schema.yml

File:
  connection: doctrine
  actAs: { Timestampable: ~ }
  columns:
    document_id: { type: integer(5), notnull: true}
    name: string(255)
    size: integer(11)
    mime: string(255)
  relations:
    Document:
      class: Document
      local: document_id
      foreign: id
      type: one
      onDelete: CASCADE
    FileData:
      local: id
      foreign: file_id
      type: one
      foreignType: one


FileData:
  connection: doctrine
  columns:
    file_id: { type: integer(6), notnull: true }
    binary_data: { type: LONGBLOB, notnull: true }
  relations:
    File: { onDelete: CASCADE, local: file_id, foreign: id, foreignType: one }

frontend/modules/file/actions/actions.class.php

<?php

class fileActions extends sfActions
{

  public function executeDownload(sfWebRequest $request)
  {
    $response = $this->getResponse();


    /** @var $file File */
    $file = $this->getRoute()->getObject();
    $this->forward404Unless($file->getDocument()->isApprovedAndShared($this->getUser()));
    $fsize = $file->getSize();

    $response->setContentType($file->getMime());
    $response->setHttpHeader('Content-Length',$fsize);
    $response->setHttpHeader('Content-Disposition','filename='.$file->getName());
    $response->setHttpHeader('Content-transfer-encoding','binary');

    $response->setContent($file->getFileData()->getBinaryData());

    return sfView::NONE;
  }

  public function executeAddFile(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST));

    /** @var $document Document */
    $document = $this->getRoute()->getObject();
    $this->forward404Unless( $document->getOffice()->getId() == $this->getUser()->getGuardUser()->getOfficeId(), $this->getContext()->getI18N()->__('textAccessForbidden'));

    $form = new FileForm();

    $files = $request->getFiles($form->getName());
    $file_name = $files['file']['name'];
    $file_already_exist = FileTable::getInstance()->getFile($document->getId(), $file_name);

    if ($file_already_exist) {
      $form = new FileForm($file_already_exist);
      $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
//      $form->getObject()->setCreatedAt(date("Y-m-d H:i:s", time()));
      $form->getObject()->setUpdatedAt(date("Y-m-d H:i:s", time()));
    }
    else {
      $form = new FileForm();
      $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
    }

    if ($form->isValid())
    {
      $form->getObject()->setDocumentId($document->getId());
      $file_result = $form->save();

      if ($file_already_exist)
        $this->getUser()->setFlash('notice', $this->getContext()->getI18N()->__("textFileReplacedOk", array('%s%'=>$file_result->getName())));
      else
        $this->getUser()->setFlash('notice', $this->getContext()->getI18N()->__("textFileUploadOk", array('%s%'=>$file_result->getName())));

      $this->redirect($this->generateUrl("document_edit",$document));
    }

    $this->getUser()->setFlash('error', $this->getContext()->getI18N()->__("textFileUploadError"));
    $this->forward("document","edit");

  }


  public function executeDelete(sfWebRequest $request)
  {
    /** @var $file File */
    $file = $this->getRoute()->getObject();

    $this->forward404Unless($request->getParameter('document_id') == $file->getDocumentId() , sprintf('The object doesn\'t belong to the document (file: %s).', $request->getParameter('id')));
    $this->forward404Unless($file = FileTable::getInstance()->find(array($file->getId() )), sprintf('Object file does not exist (%s).', $request->getParameter('id')));
    $file->delete();

    $this->getUser()->setFlash('notice', sprintf($this->getContext()->getI18N()->__("textFileDeletedOk"),$file->getName()));

    $this->redirect($this->generateUrl( "document_edit",DocumentTable::getInstance()->find(array($file->getDocumentId())) ));
  }

}

FileDataForm.class.php

class FileDataForm extends BaseFileDataForm
{
  public function configure()
  {
    unset(
      $this['file_id']
    );        
  }
}

FileForm.class.php

class FileForm extends BaseFileForm
{
  public function configure()
  {
    $this->disableCSRFProtection();
    $this->useFields(array());
    $this->widgetSchema['file'] = new sfWidgetFormInputFile(array());

    $this->setValidator('file', new sfValidatorFile(array(
     'max_size' => 1024*1024*sfConfig::get("app_max_file_size", 10) //MB
    )));


  }

  public function save($con = null)
  {

    /** @var $validated_file
     var_dump( $validated_file) */
    $validated_file = $this->getValue('file');

    /** @var $file File */
    $file = $this->getObject();
    $file->setMime($validated_file->getType());
    $file->setName($validated_file->getOriginalName());
    $file->setSize($validated_file->getSize());

    $fileData = new FileData();

    $fd = @fopen($validated_file->getTempName(), 'rb');

    $fileData->setBinaryData(fread($fd,$validated_file->getSize()));

    fclose($fd);

    $file->setFileData($fileData);
    unset($this['file']); //do not save Validated file: this is a trick :)

    return parent::save($con);
  }
}

First of all if you store data in DB do not store it in the one sigle table.
Here my example:

schema.yml

File:
  connection: doctrine
  actAs: { Timestampable: ~ }
  columns:
    document_id: { type: integer(5), notnull: true}
    name: string(255)
    size: integer(11)
    mime: string(255)
  relations:
    Document:
      class: Document
      local: document_id
      foreign: id
      type: one
      onDelete: CASCADE
    FileData:
      local: id
      foreign: file_id
      type: one
      foreignType: one


FileData:
  connection: doctrine
  columns:
    file_id: { type: integer(6), notnull: true }
    binary_data: { type: LONGBLOB, notnull: true }
  relations:
    File: { onDelete: CASCADE, local: file_id, foreign: id, foreignType: one }

frontend/modules/file/actions/actions.class.php

<?php

class fileActions extends sfActions
{

  public function executeDownload(sfWebRequest $request)
  {
    $response = $this->getResponse();


    /** @var $file File */
    $file = $this->getRoute()->getObject();
    $this->forward404Unless($file->getDocument()->isApprovedAndShared($this->getUser()));
    $fsize = $file->getSize();

    $response->setContentType($file->getMime());
    $response->setHttpHeader('Content-Length',$fsize);
    $response->setHttpHeader('Content-Disposition','filename='.$file->getName());
    $response->setHttpHeader('Content-transfer-encoding','binary');

    $response->setContent($file->getFileData()->getBinaryData());

    return sfView::NONE;
  }

  public function executeAddFile(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST));

    /** @var $document Document */
    $document = $this->getRoute()->getObject();
    $this->forward404Unless( $document->getOffice()->getId() == $this->getUser()->getGuardUser()->getOfficeId(), $this->getContext()->getI18N()->__('textAccessForbidden'));

    $form = new FileForm();

    $files = $request->getFiles($form->getName());
    $file_name = $files['file']['name'];
    $file_already_exist = FileTable::getInstance()->getFile($document->getId(), $file_name);

    if ($file_already_exist) {
      $form = new FileForm($file_already_exist);
      $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
//      $form->getObject()->setCreatedAt(date("Y-m-d H:i:s", time()));
      $form->getObject()->setUpdatedAt(date("Y-m-d H:i:s", time()));
    }
    else {
      $form = new FileForm();
      $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
    }

    if ($form->isValid())
    {
      $form->getObject()->setDocumentId($document->getId());
      $file_result = $form->save();

      if ($file_already_exist)
        $this->getUser()->setFlash('notice', $this->getContext()->getI18N()->__("textFileReplacedOk", array('%s%'=>$file_result->getName())));
      else
        $this->getUser()->setFlash('notice', $this->getContext()->getI18N()->__("textFileUploadOk", array('%s%'=>$file_result->getName())));

      $this->redirect($this->generateUrl("document_edit",$document));
    }

    $this->getUser()->setFlash('error', $this->getContext()->getI18N()->__("textFileUploadError"));
    $this->forward("document","edit");

  }


  public function executeDelete(sfWebRequest $request)
  {
    /** @var $file File */
    $file = $this->getRoute()->getObject();

    $this->forward404Unless($request->getParameter('document_id') == $file->getDocumentId() , sprintf('The object doesn\'t belong to the document (file: %s).', $request->getParameter('id')));
    $this->forward404Unless($file = FileTable::getInstance()->find(array($file->getId() )), sprintf('Object file does not exist (%s).', $request->getParameter('id')));
    $file->delete();

    $this->getUser()->setFlash('notice', sprintf($this->getContext()->getI18N()->__("textFileDeletedOk"),$file->getName()));

    $this->redirect($this->generateUrl( "document_edit",DocumentTable::getInstance()->find(array($file->getDocumentId())) ));
  }

}

FileDataForm.class.php

class FileDataForm extends BaseFileDataForm
{
  public function configure()
  {
    unset(
      $this['file_id']
    );        
  }
}

FileForm.class.php

class FileForm extends BaseFileForm
{
  public function configure()
  {
    $this->disableCSRFProtection();
    $this->useFields(array());
    $this->widgetSchema['file'] = new sfWidgetFormInputFile(array());

    $this->setValidator('file', new sfValidatorFile(array(
     'max_size' => 1024*1024*sfConfig::get("app_max_file_size", 10) //MB
    )));


  }

  public function save($con = null)
  {

    /** @var $validated_file
     var_dump( $validated_file) */
    $validated_file = $this->getValue('file');

    /** @var $file File */
    $file = $this->getObject();
    $file->setMime($validated_file->getType());
    $file->setName($validated_file->getOriginalName());
    $file->setSize($validated_file->getSize());

    $fileData = new FileData();

    $fd = @fopen($validated_file->getTempName(), 'rb');

    $fileData->setBinaryData(fread($fd,$validated_file->getSize()));

    fclose($fd);

    $file->setFileData($fileData);
    unset($this['file']); //do not save Validated file: this is a trick :)

    return parent::save($con);
  }
}
风启觞 2024-10-18 15:15:52

在列表操作中,获取适当图像对象的集合。在模板中,为每个生成一个 标记,指向另一个操作,该操作从数据库中获取图像本身,然后在设置适当的 http 标头后将其输出。

您将图像存储在数据库中的具体原因是什么?将它们存储在磁盘上(Webroot 之外的某个位置)会更有效,因此您仍然可以进行访问控制。

更新

下面是一个基本示例。我刚刚在这里输入,因此可能包含错误。

//actions.class.php
public function executeIndex(sfWebRequest $request) {
  //get the images belonging to the current gallery
  $this->images = Doctrine_Core::getTable("Image")->retrieveByGalleryId($request->getParameter("id"));
}

//indexSuccess.php
<?php foreach ($images as $image): ?>
  <img src="<?php echo url_for("image_show", $image) ?>" alt="<?php echo $image->title ?>" />
<?php endforeach>

//actions.class.php again
public function executeShow(sfWebRequest $request) {
  $image = $this->getRoute()->getObject();
  $this->getResponse()->clearHttpHeaders();
  $this->getResponse()->setContentType($image->mime_type);
  $this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename=' . $image->file_name);
  $this->getResponse()->setHttpHeader('Content-length', $image->file_size);
  readfile($image->file_name);
  return sfView::NONE;
}

In your list action, get a collection of the appropriate image objects. In the template, generate an <img> tag for each, pointing to another action, that fetches the image itself from the database, then outputs it after setting the appropriate http headers.

Any specific reason you're storing the images in the database? It'd be more efficient to store them on the disk, somewhere outside of the webroot, so you can still have access control.

update

A basic example follows. I just typed it here, so may contain errors.

//actions.class.php
public function executeIndex(sfWebRequest $request) {
  //get the images belonging to the current gallery
  $this->images = Doctrine_Core::getTable("Image")->retrieveByGalleryId($request->getParameter("id"));
}

//indexSuccess.php
<?php foreach ($images as $image): ?>
  <img src="<?php echo url_for("image_show", $image) ?>" alt="<?php echo $image->title ?>" />
<?php endforeach>

//actions.class.php again
public function executeShow(sfWebRequest $request) {
  $image = $this->getRoute()->getObject();
  $this->getResponse()->clearHttpHeaders();
  $this->getResponse()->setContentType($image->mime_type);
  $this->getResponse()->setHttpHeader('Content-Disposition', 'attachment; filename=' . $image->file_name);
  $this->getResponse()->setHttpHeader('Content-length', $image->file_size);
  readfile($image->file_name);
  return sfView::NONE;
}
幸福丶如此 2024-10-18 15:15:52
$profile_picture = base64_encode(stream_get_contents($image->getContent()));
echo '<img src="data:image/jpeg;base64,'.$profile_picture.'" />';
$profile_picture = base64_encode(stream_get_contents($image->getContent()));
echo '<img src="data:image/jpeg;base64,'.$profile_picture.'" />';
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文