Задать вопрос
@Angelxalfa

Вывод pdf из MySQL?

Здравствуйте! На одном проекте возникла необходимость хранить пдф файлы в базе данных.
Сохраняю в поле longBLOB след. кодом:
include '../../connect.php';
		$table = "".$prefix."test01";
		$city = "city";
		if ($handle = opendir(''.$_SERVER['DOCUMENT_ROOT'].'/wp-content/themes/domen/cities/'.$citie.'/bills/bill_files')) {
    echo "Файлы в папке:<br>";
    $log ='';
	$file_name = null;
	while (false !== ($file = readdir($handle))) { 
        if(preg_match("|.pdf$|",$file)){
			 if($file_name !== $file){
				echo "$file<br>";
				$pieces = explode(".", $file);
				$id = $pieces[0];
				echo $id;
				$upload=file_get_contents(''.$_SERVER['DOCUMENT_ROOT'].'/wp-content/themes/domen/cities/'.$citie.'/bills/bill_files/'.$file.'');
					  $ins=sprintf("UPDATE $table SET bill ='%s' WHERE id='$id'",mysql_real_escape_string($upload));
					  mysql_query($ins);
					  if (mysql_errno()) {echo mysql_errno() . '\n' . mysql_error() . '\n';}
					if (!$ins){$log .= "Ошибка копирования данных из файла ".$file."$date<br>". PHP_EOL;}
					else {$log .= "Данные из файла ".$file." скопированны в базу $date<br>". PHP_EOL;}				
					$file_name = $file;
			 }
		}
    }
	echo $log;
}


Вывожу обратно так:

header("Content-Type: application/pdf");
include '../../connect.php';
$table = "".$prefix."test01";
$id = "0001";
$result="SELECT bill FROM $table WHERE id='".$id."'";
$result = mysql_query($result);
$row = mysql_fetch_array($result);
echo $row['bill'];

При использовании Chrome на выходе получается исходный пдф. Но при его сохранении и попытке открытия - Файл поврежден.

Если добавить строку чтобы файл скачивался сразу
header("Content-Disposition:attachment;filename='pdf.pdf'");

получается файл pdf.pdf с размером 0 байт.

Подскажите, как правильно выводить pdf из базы данных, заранее спасибо!

В итоге проблема оказалась в этой строке при загрузке файла:
$ins=sprintf("UPDATE $table SET bill ='%s' WHERE id='$id'",mysql_real_escape_string($upload));

Убрал экранирование и изменил на
$ins = "UPDATE $table SET bill ='".$upload."' WHERE id='".$id."'";

Все заработало корректно.

За советы всем огромное спасибо! Согласен, что хранить в базе не самое лучшее решение, но сайт сейчас лежит на виртуальном хостинге и доступа к настройкам nginx я не имею, а сделать нужно "вчера"!:-) Поэтому приходится искать быстрое решение. В ближайшее время буду переносить сайт на выделенный сервак и там буду пытаться реализовать через nginx (спасибо Дмитрий Филимонов и @valerium).
  • Вопрос задан
  • 3131 просмотр
Подписаться 1 Оценить 3 комментария
Решения вопроса 2
Как принятно на русских ресурсах не отвечать на вопрос, а давай советы :) Но в этот раз совет важный и даже юзабельный.

Хранить файл в БД - плохо. Может показаться, что это удобно (например, только бэкап БД спасет всех).

Но на самом деле:
  • Растет размер БД. Что делать, если он станет запредельным из-за сохраненных там файлов?
  • Возрастает нагрузка на диски/оперативную память сервера БД.
  • Офигенно растут логи, а это дополнительная нагрузка на диск.
  • Замедлится передача данных от MySQL, т.к. там, во-первых, может быть сеть со своей пропускной способностью, а во-вторых, MySQL будет передавать большой файл маленькими частями (снова оверхед на I/O диска и сети).
  • То, что можно отдать обычным nginx'ом как статику, отдается через костыли.

Хранить блобы можно, конечно, но рано или поздно сделаете БД узким местом. Если и хранить блобы, то очень-очень маленькие, но и даже это спорно и зависит от задачи.

Поэтому отказывайтесь от идеи.

Просто в этих пдфках содержаться персональные данные пользователей и нельзя чтобы они имели прямые ссылки(доступ к ним открывается только после авторизации)

Причем здесь БД? Храните файл в том месте, которое не сервится наружу. А доступ до файла регулируйте при запросе. То есть у вас есть какой-то url для файла, там содержится его id, например. Вы проводите авторизацию: если можно забрать файл, спрашиваете у БД ссылку, где он находится на диске (а это место наружу не видно), и отдаете файл подобным образом, как делаете сейчас. НО, если ожидаются крупные файлы, читать файл нужно по частям, иначе можете закончить оперативу. В фреймворках обычно есть для этого инструменты, кстати.
Ответ написан
mramor
@mramor
нечего о себе рассказывать.
Никогда таким не заморачивался, потому не уверен в своем ответе.
получается файл pdf.pdf с размером 0 байт.

попробуйте еще добавить хедер на размер:
header('Content-Length: '.strlen($row['bill']));

возьмите вручную из поля значение и сохраните в пдф, может лежащий там файл поврежден сам по себе.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы