Я только что обсудил со своим товарищем по команде расположение загруженных пользователем изображений в галерее изображений. Я хотел бы получить более широкое представление о методах, которые мы предлагаем.
Мой товарищ по команде написал контроллер + действие, которое вызывает file_get_contents
для файла изображения, помещенного в папку, недоступную для публичного просмотра (т. Е. Вне public_html
на сервере) и отображает его через заголовок. Это безопасно, но, поскольку мы используем Zend Framework, сканирование выполняется медленно - каждый вызов контроллера образа стоит нам примерно 500 мс задержки из-за выполняемых запросов начальной загрузки. Это раздражает, поскольку в представлении галереи изображений одновременно отображается более 20 изображений.
Короче говоря, соответствующий код будет:
class ImageController extends Zend_Controller_Action {
public function showAction () {
$filename = addslashes($this->_getParam('filename'));
if(!is_file($filename)) {
$filename = APPLICATION_PATH.'/../public/img/nopicture.jpg';
}
$this->_helper->viewRenderer->setNoRender(true);
$this->view->layout()->disableLayout();
$img = file_get_contents($filename);
header('Content-Type: image/jpeg');
$modified = new Zend_Date(filemtime($filename));
$this->getResponse()
->setHeader('Last-Modified',$modified->toString(Zend_Date::RFC_1123))
->setHeader('Content-Type', 'image/jpeg')
->setHeader('Expires', '', true)
->setHeader('Cache-Control', 'public', true)
->setHeader('Cache-Control', 'max-age=3800')
->setHeader('Pragma', '', true);
echo $img;
}
}
Затем в представлении мы просто вызываем:
<img src="<?php echo $this->url(array('controller' => 'image', 'action' => 'show', 'filename' => PATH_TO_HIDDEN_LOCATION.'/filename.jpg')); ?>" />
У меня другой подход: Я предпочитаю хранить исходные изображения в скрытом месте, но как только они будут запрошены, скопируйте их в общедоступное место и предоставьте ссылку на него (с дополнительным механизмом, запускаемым cron, чтобы каждый раз стирать каталог общедоступных изображений а затем, чтобы не тратить впустую место, и robots.txt
, говорящий Google не индексировать каталог). Решение помещает файлы (по несколько в каждый данный момент) в общедоступный каталог (при условии, что кто-то знает имя файла), но также требует только помощника представления, таким образом, не запускает загрузочную программу:
class Zend_View_Helper_ShowImage extends Zend_View_Helper_Abstract {
public function showImage ($filename) {
if (!file_exists(PUBLIC_PATH."/img/{$filename}")) {
if (!copy(PATH_TO_HIDDEN_FILES."/{$filename}",PUBLIC_PATH."/img/{$filename}"))
$url = PUBLIC_PATH.'/img/nopicture.jpg';
else
$url = PUBLIC_PATH."/img/{$filename}";
} else {
$url = PUBLIC_PATH."/img/{$filename}"
}
return "{$url}";
}
}
С помощью этого помощника вызов очень прост в представлении:
<img src="<?php echo $this->showImage('filename.jpg'); ?>" />
Вопрос: Представляет ли мой подход угрозу безопасности, как заявляет моя коллега? Каковы потенциальные риски этого? И, что наиболее важно, перевешивают ли угрозы безопасности, если таковые имеются, 10-секундный выигрыш при загрузке страницы?
В случае, если это имеет значение: мы работаем над порталом сообщества, где зарегистрировано около 15 тысяч пользователей, при этом галереи очень часто используемая функция.
* Код, который я вставил, представляет собой отредактированную, упрощенную версию того, что придумал каждый из нас, просто чтобы показать механику обоих подходов.