загрузка, обработка, хранение и доставка предоставленных пользователем файлов и изображений

Позже или ранее в жизни веб-разработчиков вам придется иметь дело с файлами и изображениями, загруженными пользователями.

Общие вопросы:

Как загрузить?

современные веб-браузеры и методы позволяют несколько способов загрузки файлов, предоставленных пользователем на мой сервер. Каковы наилучшие практики и что я должен учитывать?

Как я могу обработать?

После завершения загрузки, что мне нужно знать о безопасности и дальнейшей обработки файлов

Как сохранить и доставить?

Есть ли рекомендации по хранению загруженных файлов?

отказ от ответственности: я поставил почти 30 минут на следующий ответ, первоначальный вопрос был удален, поэтому я решил задать общие вопросы, с которыми может столкнуться пользователь при работе с файлами, предоставленными пользователем. См. Мой ответ, вы можете вносить свой вклад и добавлять свои идеи и опыт

Для каждого из этих этапов нет «наилучшего» способа, но существует целая куча установленных способов и лучших практик среди множества техник и библиотек, которые могут помочь вам достичь удобной загрузки, безопасности и скорости.

По другому вопросу, который, к сожалению, был удален, я написал этот небольшой путеводитель.

Файл или изображение, внесенное пользователем, проходит через несколько этапов его жизни:

  1. сама загрузка
  2. validaton
  3. обработка для хранения (например, преобразование типа, изменение размера, создание миниатюр, …)
  4. хранения
  5. доставка на стороне входа

Это будет описано во всех шагах и, если возможно, привести примеры

1. Загрузить

Современные веб-браузеры предлагают несколько способов загрузки файла.

Самый простой способ – создать форму с простым <input type="file" name="userFile" /> . Как только форма будет отправлена, файл будет отправлен с использованием POST, и к нему можно получить доступ с суперкоммулятором $ _FILES в PHP

1.1. Простая форма в HTML

 <form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="userFile1" /> <input type="file" name="userFile2" /> <input type="submit" value="upload files" /> </form> 

Когда форма отправляется, POST-запрос отправляется в upload.php. Этот вид загрузки не очень удобен для пользователя. Ваш пользователь не увидит никакого прогресса в загрузке, и загрузка нескольких файлов будет больно

1.2. Загрузка javascript ajax

В этом решении POST выполняется асинхронно с javascript

http://www.saaraan.com/2012/05/ajax-image-upload-with-progressbar-with-jquery-and-php

1.3. Загрузка HTML 5

современные браузеры поддерживают HTML5, что позволяет очень красиво и удобно загружать маски с индикатором выполнения и предварительным просмотром – граница – это ваше собственное творчество

Например, мне очень нравится эта демонстрация: http://html5demos.com/dnd-upload

На стороне сервера

Независимо от того, какую из тех технологий загрузки вы решите использовать, загрузка будет в HTTP POST отправлена ​​на ваш скрипт. Вся дальнейшая обработка будет выполняться на сервере.

PHP копирует файл во временный путь ( upload_tmp_dir )

Есть несколько других настроек, связанных с загрузкой, которые вы можете настроить в своем php.ini или на лету с помощью ini_set : http://php.net/manual/en/ini.core.php#ini.sect.file- добавления

upload.php

 <pre> <?php print_r( $_FILES ); 

Вот как выглядит $_FILES после успешной загрузки.

  • имя: оригинальное название
  • type: предоставляемый браузером mime-type
  • размер: размер в байтах
  • tmp_name: временное имя файла на вашем сервере
  • error: коды ошибок, как описано здесь , 0, когда все пошло в файл

У каждого файла есть собственный индекс

 Array ( [userFile1] => Array ( [name] => i_love_ponies.png [type] => image/png [size] => 42233 [tmp_name] => /tmp/_x123tfsdayx134 [error] => 0 ) [userFile2] => Array ( [name] => ponies_run_my_server.png [type] => image/png [size] => 12325 [tmp_name] => /tmp/_x3123asdad3ssy [error] => 0 ) ) 

Несколько дополнительных советов

Если вы ожидаете больших файлов, рассмотрите тайм-ауты выполнения веб-сервера и php. Если загрузка занимает 10 минут, вы не хотите, чтобы ваши пользователи оказались в ошибке.

В PHP вы можете увеличить max_execution_time

2. Проверка

Вопросы, которые вы можете задать

Должен ли я разрешать только определенные файлы – какой файл я получу?

тип, который вы находите в массиве $_FILES задается браузером. Если вы хотите быть уверенным, какой тип был загружен, вы можете использовать расширение fileinfo для PHP.

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

 $allowedTypes = array( 'image/png' 'image/gif' 'image/jpeg' ); $useFiles = array(); $finfo = new finfo(FILEINFO_MIME_TYPE); foreach ( $_FILES as $index => $file ) { if ( $file['error'] === UPLOAD_ERR_OK ) { $type = $finfo->file( $file['tmp_name'] ); if ( in_array( $type, $allowedTypes ) ) { $useFiles[$index] = $file; } } } 

Я хочу установить максимальный размер файла – какой размер?

В этом случае вы можете смело полагаться на значение $_FILES['key']['size'] , размер которого равен байтам. Вы не должны просто полагаться на ограничение размера файла на стороне клиента

если говорить об изображениях, хочу ли я масштабировать или создавать миниатюры – каковы размеры изображения?

Взгляните на getimagesize, чтобы определить размеры изображения

3. Обработка

Прежде чем сохранять файл в его конечном месте, вы можете захотеть обработать его. Это время, когда вы можете

  • изменить размер изображения для последующего отображения
  • создать эскиз
  • добавить водяной знак или брендинг
  • конвертировать в другой тип. здесь нет ссылки, потому что это может быть любой тип, я уверен, что вы нашли решение для преобразования вашего .xxx в .yyy 🙂

Обычными библиотеками, используемыми для обработки изображений, являются gd lib и imagick . лично я предпочитаю gd lib. Это немного более ручная работа, но она быстрее и поставляется с большинством установок по умолчанию или проста для установки дополнительно. Imagemagick изначально имеет очень большой пул функций обработки изображений

4. Сохранение данных

Теперь пришло время поговорить о хранении. Сначала сохраните способ скопировать временный файл во временное или окончательное местоположение.

Вы должны использовать move_uploaded_file

 move_uploaded_file( $useFiles['tmp_name'], $destination ); 

Опять же, для хранения нет «лучшего способа», это зависит от вашей среды, файлов и использования. Я расскажу о нескольких

4.1. файловая система сервера

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

Чтобы сделать вашу жизнь проще, вы можете сохранить имя файла в базу данных – предпочтительнее ссылаться или ссылаться на связанные данные, такие как пользователь или местоположение.

Вы не должны сохранять все файлы в одной папке по разным причинам.

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

Вы можете сохранить его в папку для каждого пользователя

 /uploaded/user-id/file.jpg 

Если вы ожидаете большого количества файлов на пользователя, вы можете разделить контрольную сумму имени файла, чтобы получить более глубокую структуру папок

например

 $path = $_SERVER['DOCUMENT_ROOT'] . '/uploaded/' . $userId . '/' . chunk_split( md5( $useFiles['index']['name'] ), 12, '/' ); 

приведет к

 /var/www/htdocs/uploaded/1/97e262286853/d52aa8c58eb7/f0431f03/ 

4.2. База данных

Вы можете хранить ваши файлы в базе данных MySQL, используя тип blob. Я не рекомендую это вообще

4,3. Сеть доставки контента

Если вы ожидаете много трафика по всему миру, вы можете захотеть сохранить ваши файлы на CDN, например Amazon S3, с Cloudfront.

S3 – дешевое надежное хранилище для файлов размером до 5 ТБ (насколько мне известно)

http://www.9lessons.info/2012/08/upload-files-to-amazon-s3-php.html

Вам не придется беспокоиться о резервных копиях файлов, доступном размере жесткого диска, скорости доставки и т. Д. И т. Д. Cloudfront добавляет слой CDN поверх S3 с крайними местоположениями по всему миру