@rd_nino
программист-любитель

Как правильно организовать хранение файлов в базе данных MySQL (загрузка и выгрузка через PHP)?

Добрый день.
Я в PHP новичок и при реализации простенького приложения возникла проблема - файлы, загруженные в базу данных MySQL через PHP повреждаются (при передаче файла из базы клиенту размер файла увеличивается на 4-5 байт.

Сервер реализован на базе IIS + MySQL + PHP.

В базе таблица tblfiles имеет такую структуру:
CREATE TABLE `tblfiles` (
	`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'Идентификатор',
	`name` VARCHAR(250) NOT NULL COMMENT 'Оригинальное имя файла',
	`premise_id` INT(11) NOT NULL COMMENT 'Идентификатор помещения',
	`mime_type` VARCHAR(250) NOT NULL COMMENT 'mime-тип загруженного файла',
	`file_content` LONGBLOB NOT NULL COMMENT 'контент файла',
	`size` INT(11) NOT NULL COMMENT 'размер в байтах',
	INDEX `id` (`id`)
)
COMMENT='Файлы'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1


Код загрузки файлов такой:
if (isset($_FILES['files'])) 
  { 
    $premise_id = $_POST['input_item_id'];

    //пролистываем весь массив файлов по одному $_FILES['file']['name'] as $k=>$v
  foreach ($_FILES['files']['name'] as $k=>$v)
  {
    //директория загрузки
    $uploaddir = "uploads/";
    $uploadfile = $_FILES['files']['name'][$k];
       //черный список типов файлов
      $blacklist = array(".php", ".phtml", ".php3", ".php4");
      foreach ($blacklist as $item)
      {
        if(preg_match("/$item\$/i", $_FILES['files']['name'][$k]))
        {
          echo "Нельзя загружать скрипты.";
          exit;
        }
      }
       //перемещаем файл из временного хранилища
      if (move_uploaded_file($_FILES['files']['tmp_name'][$k], $uploadfile))
      {
          //подготавливаем переменные
          $mime_type = $_FILES['files']['type'][$k];
          $filename = basename($uploadfile);
          $file   = fopen($uploadfile,"rb"); //Открыли файл на чтение ($uploadfile - имя файла)
          $img_content = fread($file,filesize($uploadfile)); // Прочитали содержимое файла в переменную
          $file_size = filesize($uploadfile);
          fclose($file);
          unlink($uploadfile);
        try
          {
            //пишем данные в базу
              $stmt = $cnndb->prepare("INSERT INTO tblfiles ( name, premise_id, mime_type, file_content, size ) VALUES ( :name, :premise_id, :mime_type, :file_content, :size )");
              $stmt->bindParam(':name', $filename, PDO::PARAM_STR);
              $stmt->bindParam(':premise_id', $premise_id, PDO::PARAM_INT);
              $stmt->bindParam(':size', $file_size, PDO::PARAM_INT);
              $stmt->bindParam(':mime_type', $mime_type, PDO::PARAM_STR);
              $stmt->bindParam(':file_content', $img_content, PDO::PARAM_LOB);
              $cnndb->errorInfo();
              $stmt->execute();
          }
          catch(PDOException $e)
          {
              'Error : ' .$e->getMessage();
          }
      }
      else
        echo "<center><br>Файл не загружен, вернитесь и попробуйте еще раз.</center>";
    } 
  }


Код выдачи файла из базы такой:
$id	=	strip_tags($_GET['id']);
    $cnndb = CreateCon();
    $sql="SELECT name, file_content, mime_type FROM tblfiles WHERE id= $id"; 
	$result = $cnndb->query($sql);
	if (!$result) 
	    { 
	        die('Could not connect: ' . mysql_error()); 
	   }
 	if($row = $result->fetch(PDO::FETCH_ASSOC)) {
 		 $file_name = $row['name'];
 		 $mime_type = $row['mime_type'];
 		 $file_content = $row['file_content'];
 		header("Content-Type: $mime_type");
		header('Content-Disposition: attachment; filename="'.$file_name.'"');
		echo $file_content;
	}


Код сформирован на основе примеров, коих в интернете много, адаптирован под себя (в виде скелета, который требует доработки), работает, но где-то ошибка, а где - по причине отсутствия опыта - найти не могу.
Прошу помочь советом по приведённому коду или отослать на пример правильной организации хранения файлов в базе данных SQL.
Спасибо.
  • Вопрос задан
  • 10172 просмотра
Решения вопроса 1
В коде выдачи случайно нет закрывающего пхп тэга? Вдруг после него лишние пробелы?
попробуй еще отправлять заголовок header('Content-Length: ' . $size);
попробуй на всякий случай делать ob_clean перед отдачей, и exit после.

ну а вообще да, не стоит превращать базу в хранилище файлов.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Нет правильного способа хранения файлов в БД, потому что хранить файлы в БД не правильно.
Хранить надо пути к файлам, а сами файлы хранить в ФС.
Ответ написан
Ваш ответ на вопрос

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

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