Как сделать загрузчик файлов
Пошаговая инструкция по реализации загрузки файлов на сервер без перезагрузки страницы на PHP + Javascript
Проблема
Недавно я столкнулся с вполне, на мой взгляд, распространённой задачей: нужно обеспечить пользователю возможность загрузить на сервер любое число, скажем, картинок с комментарием к каждой из них в рамках одного интерфейса. В моём случае это было: фото товара, его описание и количество. Для наглядности прикладываю скриншот интерфейса:
Идея и алгоритм решения
Так как описания и фотографии для получения конечного результата можно изменять очень много раз, решено было осуществить следующую схему работы: фотографии загружаются на сервер на одной при клике на фото-иконку, при этом в случае успеха сервер возвращает имя картинки, а при неуспехе — «error». Соответственно, в случае успеха, фото-иконка заменяется на миниатюру загруженного фото, а в скрытое поле формы соответствующей строки сохраняется её имя, а при неуспехе мы получаем фото-иконку и пустое скрытое поле формы соответствующей строки, отвечающее за имя фото. Текстовая же информация при изменении любого поля формы отправляется на сервер вся в формате массив [имяФото, описаниеДетали, количествоШт] — это наиболее универсально: один и тот же метод отвечает за полное обновление списка товаров при их редактировании или удалении. Как известно, AJAX не умеет отправлять файлы, поэтому реализуем процедуру загрузки с помощью обычной формы, в качестве target которой укажем скрытый фрейм, который и будет перезагружаться вместо страницы.
Практическая реализация
Итак, в нашем распоряжении HTML, PHP и Javascript. Поехали:
1. Верстаем на странице форму для загрузки фото. Она содержит только один input, который мы спрячем с помощью css:
2. Создадим на странице скрытый iframe, который и будет перезагружаться в результате отправки формы с файлом:
3. Верстаем таблицу товаров, с которой и будет работать пользователь:
3. Пишем PHP-код загрузки файла:
Мой проект на CodeIgniter, поэтому код вот такой, но в целом, суть в следующем: мы просто загружаем и переименовываем полученный из формы файл, если всё проходит успешно, выводим в наш iframe его имя, если нет — «error».
4. Пишем Javascript, который будет контролировать весь процесс:
Вот, собственно, и весь процесс.
Если возникнет такая необходимость, сделаю демо процесса отдельным блоком и прикреплю сюда ссылку, а так же дам исходники.
Загрузка файла с помощью HTML формы
Раздел содержит информацию о том, как из браузера загрузить файлы в Object Storage с помощью HTML формы.
Примечание
Через форму нельзя загрузить объекты размером более 5 ГБ (см. Квоты и лимиты).
Общее описание
Если вы хотите, чтобы пользователи вашего сервиса могли загружать файлы в ваш бакет напрямую из браузера, то:
Чтобы устанавливать правила и ограничения на загрузку файлов, к форме необходимо приложить политику безопасности. Политика не нужна только в том случае, если ваш бакет доступен для публичной записи без ограничений.
Для создания формы выполните следующие действия:
HTML-форма
Общий вид HTML страницы с формой для загрузки файла:
HTML-форма описывается тегом и состоит из объявления и полей.
Объявление формы содержит атрибуты:
Поля формы содержат подробное описание запроса к Object Storage и ограничений, которые применяются к этому запросу.
Форма и ее поля должны быть в кодировке UTF-8. Установите атрибут charset тега страницы в значение UTF-8.
Поля формы
Object Storage поддерживает механизмы подписи формы AWS Signature V2 и V4. От механизма подписи зависят названия и состав полей формы. AWS Signature V2 поддержана только для совместимости, по возможности не используйте ее.
Примечание
Дальнейшее описание актуально только при использовании AWS Signature V4.
Описание полей формы:
Необходимо, если в форме есть политика безопасности.
Необходимо, если в форме есть политика безопасности.
Все заголовки, начинающиеся с x-amz-meta- Object Storage воспринимает как пользовательские, не обрабатывает их и сохраняет в том виде, в котором они переданы.
Политика безопасности
HTML-форма содержит политику безопасности, которая накладывает ограничения на файлы, которые можно загрузить.
Политика безопасности представляет собой документ JSON и может выглядеть, например, следующим образом:
Поле conditions содержит набор правил для полей формы. Хотя бы одно правило должно быть указано для каждого поля формы.
Правила политики безопасности могут быть следующих типов:
Тип правила | Описание |
---|---|
Точное совпадение | Поле в форме должно иметь в точности то значение, которое указано в политике. Если поле key имеет форму шаблона, то политика применяется после подстановки в шаблон заданного пользователем имени файла. Подпись политики безопасностиПример генерирования формы с помощью boto3Для генерирования полей формы воспользуемся boto3 Python SDK: Скрипт вернет документ JSON следующего вида: Используя значения из выданного документа, можно построить HTML-страницу с формой для отправки файла: PHP class для скачки и закачки файлов на сервер ПредисловиеВ интернете есть много информации о том как скачивать файлы с сервера и загружать файлы на сервер, а также между серверами. Но нигде нет простого решения которое было бы более ли менее универсально. И лишь благодаря единичным статьям, кусочкам информации с форумов и всяким комментариям удалось собрать пазл воедино. Я не утверждаю что мое решение полностью универсально, но очень удобное во многих случаях, хотя это вам решать. Если у кого-либо возникнет желание улучшить мое решение этого вопроса и хватает знаний в этом направлении, то я буду рад, если вы сделаете какие-либо исправления или добавления к коду который лежит в открытом доступе на GitHub. А теперь к делу, функции класса CargaDes: Для начала нужно скачать и подключить класс CargaDes: 1. Отдача файла через браузер без показа его места хранения с возможностью докачки и регулирования скоростиЭтот метод очень похож на Drupal и иже с ним: Я добавил еще отдачу с помощью Apache, но должна быть включена директива XSendFile On Сразу после выполнения метода браузер выдаст окно для сохранения файла 2. Загрузка файла/ов на сервер через браузер с индикатором прогрессаПосле выполнения метода появится кнопка для выбора файлов и кнопка для загрузки файлов. Индикатор будет появляться для каждого выбранного файла в отдельности. 3. Скачивание файлов с удаленного сервера на свой сервер4. Отдаем файл на удаленный сервер со своего сервераПо итогу хочу сказатьЕсли этот класс поможет хотя бы одному человеку я буду очень рад этому. Как я уже говорил в начале буду рад конструктивной критике и дополнениям которые могут привести к улучшению класса. Ссылка на CargaDes.class. Изменил в статье способы использования класса. И добавил описание того что изменилось в классе. Вот закончил работу над ошибками, если это можно так назвать. Что было не сделано: В целом я постарался исправить, то о чем говорили в комментариях, если будут найдены еще какие либо недочеты или ошибки — пишите постараюсь исправить. Благодарю за конструктивную критику webdevium и alutskevich, если бы мог, то плюсанул бы вам обязательно. Так же благодарю всех остальных т.к. у меня появилось понимание моей главной ошибки и родилось пару идей. HTML5 File API: множественная загрузка файлов на серверКогда передо мной в очередной раз встала задача об одновременной загрузке нескольких файлов на сервер (без перезагрузки страницы, само собой), я стал блуждать по интернетам в поисках довольно корявого jQuery-плагина, который позволяет имитировать ajax-загрузку файла (того самого плагина, который со скрытым фрэймом: от java- и flash- плагинов сразу было решено отказаться). В процессе поиска я вспомнил, что в грядущем стандарте html 5 возможности по работе с файлами должны быть существенно расширены, и часть этих возможностей доступна уже сейчас. В итоге было решено опробовать их в действии. Рассматривать возможности File API будем на примере одновременной загрузки нескольких картинок на сервер. В конце статьи приводится готовое решение, оформленное в виде jQuery-плагина. Работающий пример можно увидеть по адресу http://safron.pro/playground/html5uploader/, ниже приведены только наиболее важные фрагменты кода. Для начала разберемся с html-кодом. Нам понадобится дефолтный элемент input, контейнер для перетаскивания файлов и список ul, куда мы будем помещать миниатюрки изображений: Теперь перейдем к JavaScript (обратите внимание, что я использовал jQuery для упрощения манипуляций с DOM. Тот, кто по каким-либо причинам захочет отказаться от jQuery, сможет без труда переделать скрипты таким образом, чтобы обойтись без него). Сначала сохраним в переменных ссылки на html-элементы, снявшиеся в главных ролях. Далее определим обработчики событий для стандартного поля выбора файлов и для области, куда можно будет перетаскивать файлы. И в том и в другом случае в обработчике мы получаем доступ к объекту FileList, который по сути представляет собой массив объектов File. Этот массив передается функции displayFiles(), текст которой приведен ниже. Объект File содержит метаданные о файле, такие как его имя, размер и тип (в формате MIME, например, image/gif) соответственно в свойствах name, size и type. Для доступа же к содержимому файла существует специальный объект FileReader. Внутри функции displayFiles() мы проходимся по переданному массиву файлов и сначала отсеиваем те, которые не являются изображениями. Далее для каждого изображения создается элемент списка li, куда помещается пустой пока элемент img (обратите внимание, что в кажом элементе li также создается свойство file, содержащее соответствующий объект). После чего создается экземпляр FileReader и для него определяется обработчик onload, в котором данные передаются прямо в атрибут src созданного ранее элемента img. Метод readAsDataURL() объекта FileReader принимает параметром объект File и запускает чтение данных из него. В результате для всех выбранных через стандартное поле или перетащенных прямо в браузер картинок, мы видим их миниатюры (искусственно уменьшенные до 150 пикселей). Что еще осталось сделать? Осталось только реализовать саму загрузку всех выбранных файлов на сервер. Для этого создадим какую-нибудь кнопку или ссылку, при нажатии на которую останется только пробежаться по всем созданным элементам li, прочитать их свойство file и передать в функцию uploadFile(), текст которой приведен ниже. Отмечу, что здесь для упрощения я реализовал загрузку через функцию, а в реальном примере, расположенном по адресу http://safron.pro/playground/html5uploader/, я собрал все действия по загрузке в объект uploaderObject, при создании которого можно передать дополнительные параметры, такие как функции обратного вызова для получения информации о процессе загрузки. Здесь создается экземпляр уже знакомого нам объекта FileReader, точно так же, как и выше; ему присваивается обработчик события onload, в котором создается XMLHttpRequest (к сожалению, пока нельзя воспользоваться ajax-интерфейсом jQuery, поскольку там еще не предусмотрена загрузка файлов). В XMLHttpRequest второй версии появилось свойство upload, содержащее объект-загрузчик, который может обрабатывать события progress, load и error (подробнее см. http://www.w3.org/TR/XMLHttpRequest2/#xmlhttprequesteventtarget). В примере выше показана только обработка события progress. Далее присваиваем обработчик завершения запроса самому реквесту (в отличие от событий объекта-загрузчика он вызывается уже тогда, когда все данные загружены и ответ от сервера получен), добавляем два дополнительных заголовка и формируем тело запроса, читая данные из свойства result объекта FileReader. После этого загрузка запускается. Отмечу только, что по нынешней спецификации W3C подразумевается, что метод send() объекта XMLHttpRequest может принимать в параметре бинарные данные, что успешно и реализовано в Google Chrome, однако в Firefox сделано по-своему, через особый метод sendAsBinary(). Поэтому перед началом отправки проверяем, определен ли метод sendAsBinary() в объекте реквеста, и, если да, используем его. Вот, собственно, и все. С нетерпением ждем утверждения и распространения html 5! Кое-какие ссылкиUPD Использованные источникиUPD2 В демке (которая переехала немного на другой адрес) был добавлен пример отправки картинки из canvas. На данный момент эта возможность работает в FF, Chrome, IE10. Исходный код ныне доступен на GitHub. Замечания, предложения, улучшения приветствуются! Как сделать загрузчик файловЭти четыре программы помогут вам загрузить практически любой сайт к себе на компьютер. Очень полезно, если вы боитесь потерять доступ к любимым статьям, книгам, инструкциям и всему остальному, что могут удалить или заблокировать. 1. HTTrackHTTrack позволяет пользователям загружать сайт из интернета на жесткий диск. Программа работает путем копирования содержимого всего сайта, а затем загружает все каталоги, HTML, изображения и другие файлы с сервера сайта на ваш компьютер. При просмотре скопированного сайта HTTrack поддерживает исходную структуру ссылок сайта. Это позволяет пользователям просматривать его в обычном браузере. Кроме того, пользователи могут нажимать на ссылки и просматривать сайт точно так же, как если бы они смотрели его онлайн. HTTrack также может обновлять ранее загруженные сайты, а также возобновлять любые прерванные загрузки. Приложение доступно для Windows, Linux и даже для устройств на базе Android. 2. SiteSuckerЕсли вы твердо придерживаетесь экосистемы Apple и имеете доступ только к Mac, вам нужно попробовать SiteSucker. Программа, получившая такое название, копирует все файлы веб-сайта на жесткий диск. Пользователи могут начать этот процесс всего за несколько кликов, что делает его одним из самых простых в использовании инструментов. Кроме того, SiteSucker довольно быстро копирует и сохраняет содержимое сайта. Однако помните, что фактическая скорость загрузки будет зависеть от пользователя. 3. Cyotek WebCopyCyotek WebCopy — инструмент, позволяющий пользователям копировать полные версии сайтов или только те части, которые им нужны. К сожалению, приложение WebCopy доступно только для Windows, но зато оно является бесплатным. Использовать WebCopy достаточно просто. Откройте программу, введите целевой URL-адрес и все. Кроме того, WebCopy имеет большое количество фильтров и опций, позволяющих пользователям скачивать только те части сайта, которые им действительно нужны. Эти фильтры могут пропускать такие вещи, как изображения, рекламу, видео и многое другое, что может существенно повлиять на общий размер загрузки. 4. GetLeftЭтот граббер с открытым исходным кодом существует уже давно, и на это есть веские причины. GetLeft — это небольшая утилита, позволяющая загружать различные компоненты сайта, включая HTML и изображения. GetLeft очень удобен для пользователя, что и объясняет его долговечность. Для начала просто запустите программу и введите URL-адрес сайта, затем GetLeft автоматически анализирует веб-сайт и предоставит вам разбивку страниц, перечисляя подстраницы и ссылки. Затем вы можете вручную выбрать, какие части сайта вы хотите загрузить, установив соответствующий флажок. После того, как вы продиктовали, какие части сайта вы хотите зазрузить, нажмите на кнопку. GetLeft загрузит сайт в выбранную вами папку. К сожалению, GetLeft не обновлялся какое-то время. Спасибо, что читаете! Подписывайтесь на мои каналы в Telegram, Яндекс.Мессенджере и Яндекс.Дзен. Только там последние обновления блога и новости мира информационных технологий. Респект за пост! Спасибо за работу!Хотите больше постов? Узнавать новости технологий? Читать обзоры на гаджеты? Для всего этого, а также для продвижения сайта, покупки нового дизайна и оплаты хостинга, мне необходима помощь от вас, преданные и благодарные читатели. Подробнее о донатах читайте на специальной странице. Заранее спасибо! Все собранные средства будут пущены на развитие сайта. Поддержка проекта является подарком владельцу сайта.
|