Я подумал о том, чтобы проголосовать, чтобы закрыть этот дубликат, но название довольно хорошее, и, просматривая другие вопросы, я не нашел полного ответа на общий вопрос. Такого рода вопросы выдают отсутствие понимания основ HTTP, поэтому вместо этого я написал длинный ответ. Я немного замутил, но любому, кто понимает следующее, вероятно, не нужно будет задавать вопрос, подобный этому. Или, если они это сделают, они смогут задать более конкретный вопрос.
Первый - Если вы храните изображения или другие файлы в базе данных, остановите и пересмотрите свою архитектуру. СУБД не очень оптимизированы для работы с BLOB. Существует ряд (нереляционных) баз данных, специально настроенных для обработки файлов. Их называют файловые системы , и они действительно хороши в этом. По крайней мере, в 95% случаев, когда я обнаружил, что обычные файлы застряли в СУБД, это было бессмысленно. Итак, во-первых, рассмотрим , а не для хранения данных файла в базе данных, использования файловой системы и хранения небольших данных в базе данных (пути, если необходимо, часто вы можете организовать свою файловую систему, так что все, что вам нужно, это уникальный идентификатор).
Итак, вы уверены, что хотите сохранить свой BLOB-объект в базе данных?
В этом случае , вам необходимо понять, как работает HTTP. Не вдаваясь в подробности, всякий раз, когда какой-либо клиент запрашивает URL (делает HTTP-запрос), сервер отвечает HTTP-ответом. HTTP-ответ состоит из двух основных частей: заголовков и данных. Две части разделены двумя последовательными символами новой строки.
Заголовки на проводе - это простые пары ключ / значение в виде простого текста, которые выглядят следующим образом:
Name: value
и разделены новой строкой.
Данные в основном BLOB. Это просто данные. Способ интерпретации данных определяется (клиентом) на основании значения заголовка Content-Type, который его сопровождает. В заголовке Content-Type указывается Тип интернет-медиа данных, содержащихся в разделе данных.
Посмотри как работает
В этом нет ничего волшебного. Для обычной HTML-страницы весь ответ читается человеком. Попробуйте следующее:
$ telnet google.com 80 # connect go google.com on port 80
Вы увидите что-то вроде:
Trying 74.125.113.104...
Connected to google.com.
Escape character is '^]'.
Теперь наберите:
GET /
(с последующим возвратом).
Вы только что сделали очень простой HTTP-запрос! И вы, вероятно, получили ответ. Посмотрите на ответ. Вы увидите все заголовки, за которыми будет пустая строка, а затем HTML-код главной страницы Google.
И что?
Итак, теперь вы знаете, что делают веб-серверы. Они принимают запросы (например, GET /
) и возвращают ответы (состоящие из заголовков, за которыми следует пустая строка (два последовательных перевода строки), за которыми следуют данные).
Теперь пришло время понять, что:
Ваше веб-приложение на самом деле представляет собой настраиваемый веб-сервер
Весь код, который вы пишете, принимает любой запрос и переводит его в HTTP-ответ. Таким образом, вы в основном просто делаете специализированную версию apache, или IIS, или nginx, или lighty, или чего-то еще.
Теперь стандартным способом, которым веб-сервер обычно обрабатывает запросы, является поиск файла в каталоге (корень документа), поиск по нему, чтобы выяснить, какие заголовки отправлять, а затем отправка этих заголовков, а затем содержимое файла.
Но, хотя ваш веб-сервер делает все это магическим образом для файлов в файловой системе, он совершенно не знает о некотором BLOB-объекте в СУБД. Так что ты должен сделать это сам.
Если вы знаете, что содержимое вашего BLOB - это, скажем, изображение JPG, которое должно быть названо на основе столбца «name» в той же таблице, вы можете сделать что-то вроде:
<?php
$result = query('select name, blobdata from table where id = 5');
$row = fetch_assoc($result);
header('Content-Type: image/jpeg');
echo $row['blobdata'];
?>
(Если вы хотите намекнуть, что браузер должен загрузить файл вместо его отображения, вы можете использовать дополнительный заголовок, например: header('Content-Disposition: attachment; filename="' . $row['name'].'"');
)
PHP достаточно умен, чтобы предоставить функцию header (), которая устанавливает заголовки и следит за тем, чтобы они отправлялись первыми (и отделялись от данных). Как только вы закончите настройку заголовков, вы просто отправите свои данные.
Пока ваши заголовки предоставляют клиенту достаточно информации о том, как обрабатывать полезную нагрузку данных, все очень просто.
Hooray.