Как отправить файл на сервер js
На первый взгляд кажется: “Что может быть сложного в загрузке файла на сервер”? Но, оказывается, не всё так просто. Мы настолько привыкли к готовым встроенным в языки иструментам, что перестали понимать как они работают. Давайте немного погрузимся в тему и разберём, как же загрузить файл на сервер и подготовить его к дальнейшей обработке на примере Node.js.
Вопрос первый: Content-Type
Передача файла из HTML-формы: Content-Type: multipart/form-data
Первый способ и наверное самый распространнённый — это передача файла из HTML-формы. Если особо не мудрить с JavaScript на клиенте, то файл, прикреплённый через поле <input type="file"> , отправится на сервер именно таким способом. Представим, что у нас есть следующая форма на странице:
На том месте, где у меня многоточия, на самом деле, очень много всего. Если кому интересно узнать, как на самом деле передаются файлы по сети, можно перехватить уходящие запросы со своего компьютера с помощью программы Wireshark.
Передача голых файлов: Content-Type: image/png
Проще всего показать пересылку таких файлов на примере утилиты cUrl.
Посмотрим что говорит Wireshark:
Видим, что таким методом отправляется только наш файл и ничего более. В большинстве случаев именно это и нужно, чтобы сделать качественный, красивый и удобный интерфейс. Так же можно заметить, что используется метод PUT. Никто, конечно, не мешает поменять руками на POST, но обычно при таком типе передачи используется именно PUT.
Вопрос второй: проверка файла на стороне сервера
Давайте сформируем полный список того, что нужно проверить на сервере, прежде чем вернуть пользователю ответ с кодом 201 Created (файл загружен):
- Если Content-Length установлен, то он должен быть меньше установленного лимита. Если это не так, то вернуть код 413 Request Entity Too Large .
- Если Content-Type установлен, то он должен быть одним из разрешённых. Если это не так, то вернуть код 422 Unprocessable Entity .
- Расширение загружаемого файла, должно быть одним из разрешённых. Если это не так, то вернуть код 422 Unprocessable Entity .
- Фактический размер файла должен быть меньше установленного лимита.
- Файл должен быть полностью и без ошибок загружен на сервер. Если это не так, то вернуть код 500 Internal Server Error .
На первый взгляд всё просто. Но есть один нюанс: всё было бы просто, если бы использовалась передача с Content-Type: multipart/form-data . Для такого типа загрузки файлов написано бесчисленное множество библиотек для Node.js, а во многих языках забота о загрузке файлов на сервер таким способом и вовсе снята с программиста. Например, в PHP мы просто можем использовать массив $_FILES . Т.е. язык гарантирует, что файл уже есть на сервере и остаётся только с ним работать. В Node.js такого поведения можно добиться с помощью следующих библиотек:
-
— отличное решение если вы используете фреймворк Express. — более низкоуровневое решение, чем Multer. Но функционала в нём не меньше. Отлично можно приспособить к любому используемому фреймворку.
Но всё не так радужно, если мы не используем multipart/form-data . В этом случае во многих языках нам самим придётся позаботиться о сохранение файла куда-нибудь на сервер (например в /tmp ). Рассмотрим как это можно сделать на Node.js.
Из всего выше сказанного следует, что нам придётся работать с потоками. Это означает, что к нам будут поступать данные маленькими кусочками — чанками (chunk). Мы должны эти кусочки сохранять.
Сразу скажу: поток это такой объект, который порождает события (для искушённых — имплементирует EventEmitter ). Нам нужно слушать эти события и как-то на них реагировать. Событие поступления нового чанка называется в Node.js data . Т.е. нам как минимум нужно написать обработчик события data .
К сожалению, люди на просторах интернета чаще предлагают одно в корне неверное решение. (Я конечно нагнетаю. На самом деле это решение жизнеспособно, но влечёт за собой ряд проблем.)
Давайте посмотрим, как делать НЕ НАДО. Привожу пример обработчика события data . В данном примере request — это объект запроса.
Что же здесь не так? А то, что пришедшие чанки сохраняются в переменную, которая, в свою очередь, хранится в оперативной памяти. Это порождает потенциальную уязвимости. Да и вообще: зачем нам лишний раз занимать ОЗУ, когда можно этого не делать?
Поэтому привожу полный листинг кода веб-сервера, загружающего файл к себе и производящего все нужные проверки:
Это всё. Теперь загрузка файлов не будет забивать нам оперативку. Можно запустить сервер и проверить, выполнив в консоле:
Если у вас что-то не работает, удостоверьтесь, что используете свежую версию Node.js. Данный код точно работает на Node.js v7.4.0.
Что нам понадобилось из сторонних библиотек:
-
— для проверки Content-Type. — для создания временного файла на диске для сохранения потока.
Что я не осветил в данной статье: Transfer-Encoding: chunked . Это уже на самостоятельное прочтение. Но стоит заметить, что данных сниппет будет работать и с этим заголовком.
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Далее – обо всём по порядку.
Стадия отправки
На стадии отправки для получения информации используем объект xhr.upload . У этого объекта нет методов, он только генерирует события в процессе отправки. А они-то как раз и нужны.
Вот полный список событий:
Пример установки обработчиков на стадию отправки:
Стадия скачивания
На этой фазе xhr.upload уже не нужен, а в дело вступают обработчики событий на самом объекте xhr . В частности, событие xhr.onprogress содержит информацию о количестве принятых байт ответа.
Все события, возникающие в этих обработчиках, имеют тип ProgressEvent, то есть имеют свойства loaded – количество уже пересланных данных в байтах и total – общее количество данных.
Демо: загрузка файла с индикатором прогресса
Мы, для примера, рассмотрим загрузку файла с индикацией прогресса. Это требует от браузера поддержки File API, то есть исключает IE9-.
Форма для выбора файла с обработчиком submit :
Мы получаем файл из формы через свойство files элемента <input> и передаём его в функцию upload :
Этот код отправит файл на сервер и будет сообщать о прогрессе при его отправке ( xhr.upload.onprogress ), а также об окончании запроса ( xhr.onload , xhr.onerror ).
Полный пример индикации прогресса при загрузке, основанный на коде выше:
Событие onprogress в деталях
При обработке события onprogress есть ряд важных тонкостей.
Можно, конечно, их игнорировать, но лучше бы знать.
Заметим, что событие, возникающее при onprogress , имеет одинаковый вид на стадии отправки (в обработчике xhr.upload.onprogress ) и при получении ответа (в обработчике xhr.onprogress ).
Оно представляет собой объект типа ProgressEvent со свойствами:
Сколько байт уже переслано.
Имеется в виду только тело запроса, заголовки не учитываются.
Если true , то известно полное количество байт для пересылки, и оно хранится в свойстве total .
Общее количество байт для пересылки, если известно.
А может ли оно быть неизвестно?
Ещё особенности, которые необходимо учитывать при использовании onprogress :
Событие происходит при каждом полученном/отправленном байте, но не чаще чем раз в 50 мс.
В процессе получения данных, ещё до их полной передачи, доступен xhr.responseText , но он не обязательно содержит корректную строку.
Можно до окончания запроса заглянуть в него и прочитать текущие полученные данные. Важно, что при пересылке строки в кодировке UTF-8 кириллические символы, как, впрочем, и многие другие, кодируются 2 байтами. Возможно, что в конце одного пакета данных окажется первая половинка символа, а в начале следующего – вторая. Поэтому полагаться на то, что до окончания запроса в responseText находится корректная строка нельзя. Она может быть обрезана посередине символа.
Исключение – заведомо однобайтные символы, например цифры или латиница.
Сработавшее событие xhr.upload.onprogress не гарантирует, что данные дошли.
Событие xhr.upload.onprogress срабатывает, когда данные отправлены браузером. Но оно не гарантирует, что сервер получил, обработал и записал данные на диск. Он говорит лишь о самом факте отправки.
Поэтому прогресс-индикатор, получаемый при его помощи, носит приблизительный и оптимистичный характер.
Файлы и формы
Выше мы использовали xhr.send(file) для передачи файла непосредственно в теле запроса.
При этом посылается только содержимое файла.
Если нужно дополнительно передать имя файла или что-то ещё – это можно удобно сделать через форму, при помощи объекта FormData:
Создадим форму formData и прибавим к ней поле с файлом file и именем "myfile" :
Данные будут отправлены в кодировке multipart/form-data . Серверный фреймворк увидит это как обычную форму с файлом, практически все серверные технологии имеют их встроенную поддержку. Индикация прогресса реализуется точно так же.
Но мы сделаем интереснее, отправим файлы с помощью ajax, без перезагрузки страницы. А также посмотрим, как валидировать файлы на клиенте и сервере, а именно проверять максимальный размер загружаемых файлов и допустимые расширения.
Суть задачи
Для нетерпеливых сразу ссылки на демо приложения и исходники
Подготовим шаблон проекта.
В корень проекта положим файл index.html, в папку js файлы jquery.min.js и main.js (не забудем их подключить в index.html). Серверный код будет выполнять upload.php из папки php, а для полученных файлов создадим папку upload.
Получится так:
html-заготовка формы
Создадим простейшую форму в index.html
Заметим, что никаких атрибутов, вроде enctype у формы или name у input-ов, навешивать не нужно - все сделает javascript.
Базовый клиентский код
Мы создали модуль приложения app, и в методе init подключили обработку сабмита формы. В функции submitForm данные для отправки готовятся с помощью объекта formdata соответствующего класса FormData. Перебирая все поля выбора файлов .js-photos, мы добавляем файлы к этому объекту методом append. Обратите внимание на название photos[] - квадратные скобки обязательны, так как в противном случае на сервер попадет не массив файлов, а только один.
Валидацию пока не делаем, рассмотрим ее ниже. А пока переходим к серверной части.
Принимаем файлы на сервере и перемещаем в нужную папку
Код обработки файлов на сервере довольно типовой, сначала привожу его, а потом кратко поясню
Сначала мы извлекаем массив файлов из $_FILES['photos'] и отпределяем папку назначения - куда мы копируем искомые файлы. PHP предварительно копирует файлы во временную папку, свойство tmp_name из $_FILES даст нам полный путь к этому временному файлу. Далее перебираем наш массив и перемещаем файлы в нужную папку под тем же названием, с которым он пришел с клиента. Этим занимается функция move_uploaded_file. В конце возвращаем клиенту успешный код ответа.
Валидация файлов на клиенте
- 1. Выбран ли вообще файл
- 2. Не превышает ли его размер максимальный
- 3. Подходит ли файл по формату
Например, ошибка может выглядеть так.
Это означает, что в input[0] (в первом по счету поле) пользователь добавил файл test.pdf, формат которого не поддерживается, так как мы просим изображения. Это одна ошибка валидации. А массив таких ошибок и будет результатом выполнения функции. Если ошибок нет, все файлы выбраны и заданы правильно, то вернем пустой массив.
Впрочем, сейчас посмотрим, как это работает. Добавим функцию валидации validateFiles.
В параметре options мы передаем объект из трех полей: $files, maxSize и types. Соответственно, это jQuery-массив элементов input, максимальный размер файла в байтах и массив допустимых типов-расширений файлов, например, image/jpg, image/png или application/pdf - список типов легко можно загуглить.
Мы перебираем массив файлов и последовательно делаем проверки. Сначала смотрим, выбран ли вообще файл. Если нет, добавляем в результирующий массив ошибок пукнт с кодом no_file. Это будет объект-ошибка - имени предсказуемо нет. Дальше мы сразу переходим к следующему файлу, проверит размер и расширение мы не сможем.
Проверка на максимальный размер в случае неуспеха вернет объект , а несоответствие типа -
Обратите внимание, если в одном файле ловится несколько ошибок (максимум две в нашем случае), например, test.pdf слишком большого веса, то в результате мы получим 2 объекта. Имеет смысл группировать эти ошибки по имени файла, но не хочется усложнять код. В конце концов, если это необходимо, Вы сможете обработать выводимый результат как угодно.
Функцию написали, осталось задействовать ее в основном потоке кода. Немного расширим код submitForm:
Как видим, мы добавили вызов validateFiles с нужными параметрами. Максимальный размер файла ограничим 2 Мб, а типы возьмем jpg и png-картинки. После вызова проверяем, не пустой ли массив полученных ошибок, и если таки не пустой, то выводим результаты в консоль и выходим из функции сабмита. Файлы на сервер не уйдут.
Как обрабатывать ошибки и показывать их пользователю - дело исключительно хозяйское :-) Нам сейчас главное убедиться, что наша валидация работает.
Клиенсткий код закончен, можете побаловаться с файлами, добавить или убрать форматы разрешенных типов или изменить максимальный размер. Наш клиентский код должен точно реагировать на все попытки загрузить "неправильные" файлы. А мы переходим к валидации на стороне сервера.
Валидация файлов на сервере
Вообще для посетителей сайта будет срабатывать клиентская валидация. Тем самым наши посетители получат мгновенную обратную связь, а сервер освободится от ненужной работы. Но в случае получения пользовательских данных всегда нужно проводить дополнительную валидацию на стороне сервера. Этим мы и займемся.
php-шная функция валидации будет проверять ровно те же параметры, что и клиентская. Но кроме двух пунктов: проверки на наличие файла и возврат индекса. Это связано с тем, что мы проверяем все файлы пришедшие с клиента и не знаем, что некоторые клиент мог не заполнить. Лучше увидеть на примере. Напишем саму функцию
Обращаю внимание, что для синхронизации клиента и сервера в обеих функциях валидации используется одинаковый формат объекта-ошибки и коды ошибок. Это облегчит нам обработку ошибок в интерфейсе независимо от того, сработала ли валидация клиентская или серверная.
После этого остается использовать написанную функцию в основном коде
Вот и все. Как видим, валидация на сервере подключена ровно таким же способом, как и на клиенте.
Чтобы убедиться, что и серверная валидация успешно работает, закомментируйте одну строку в main.js
Например, если Вы пропустите первое поле, во второе загрузите pdf-ку, а в третье - валидную картинку, то увидите примерно такую картину
Спонсор поста CRM для интернет-торговли
CRM c мессенджерами как единое целое для продаж и обслуживания во всех самых популярных мессенджеров и соц. сетях.
Интеграция с популярными мессенджерами позволяет обхватить максимальное количество источников поступления новых заказов.
Преимущества нашей CRM:
Возможность продаж в соцсетях и мессенджерах.
Вся история предыдущих заказах и коммуникациях.
Возможный чат с клиентом из любого раздела CRM
Наличие Bot API для чат-ботов.
Демо режим.
Попробуйте retailCRM в действии Тариф «Профессиональный» 14 дней бесплатно
Предварительные требования
Я также предполагаю, что вы используете современный браузер, который поддерживает объект FormData: FormData – Web APIs | MDN. Это то, что делает процесс намного проще.
Загрузка одного файла
Итак, начнем с загрузки одного файла. Для этого я создал простой компонент, который содержит input:
Обработка загрузки файла
Первое, что мы сделаем, это добавим метод handleFileUpload() к нашему объекту methods, который даст нам отправную точку для реализации:
В этом методе мы передадим локальной переменной file значение загруженного файла. При использование современного браузера, это будет объект FileList – Web APIs | MDN, который содержит объекты File: File – Web APIs | MDN. FileList не может редактироваться пользователем напрямую из соображений безопасности. Тем не менее, мы можем разрешить пользователям выбирать и отменять выбор файлов по мере необходимости, что мы рассмотрим позже.
Давайте добавим это прямо сейчас к нашему компоненту Vue. В нашем методе data() добавьте:
Теперь у нас есть что использовать в нашем методе handleFileUpload()! Давайте добавим следующий код в метод handleFileUpload():
Отправляем файл на сервер через Axios
Теперь мы реализуем наш запрос axios.
Первое, что нам нужно сделать, это реализовать объект FormData следующим образом:
Мы просто добавляем файловую переменную, в которой хранятся наши данные. Далее, если вы захотите использовать этот код в производство вам нужно будет добавить проверку, чтобы убедиться, что переменная file фактически содержит файл.
Наш запрос должен выглядеть следующим образом:
В остальной части нашего запроса мы обрабатываем метод обратного вызова для успешного запроса, который можно использовать для отображения уведомления, и мы обрабатываем обратный вызов в случае сбоя, который можно использовать для предупреждения пользователя о неудачной загрузке.
Наш компонент SingleFile.vue, используемый для тестирования, полностью будет выглядит следующим образом:
В следующем разделе мы реализуем загрузку нескольких файлов. В этом нет ничего особенного, но я укажу на изменения!
Загрузка нескольких файлов
Обработка нескольких файлов очень похожа на загрузку одиного файла. Мы начнем с шаблона, который будет выглядеть следующим образом в нашем компоненте Vue:
Метод загрузки нескольких файлов handleFileUploads()
Он очень похож на загрузку одного файла, за исключением того, что мы добавим все файлы в наш массив, если пользователь выберет более одного. Во-первых, давайте добавим новое хранилище данных в компонент Vue и присвоим этой переменной имя files:
Теперь у нас есть локальная переменная для хранения наших файлов. Теперь мы можем сделать наш метод handleFileUploads():
Он позволяет получить все файлы из FilesList из нашей загрузки файлов и сохранить их локально.
Реализация метода submitFiles()
Как и в последнем методе, сначала инициализируем объект FormData():
Наш компонент MultipleFiles.vue должен выглядеть следующим образом:
Следующим шагом мы позволим пользователям редактировать файлы, которые они выбрали, чтобы они случайно не загрузили файл, который им не нужен.
Разрешение пользователям редактировать выбранные файлы перед загрузкой
При загрузке нескольких файлов вы можете случайно выбирать файл, который вы НЕ захотите загружать. Это кажется достаточно простым для реализации, пока вы не обнаружите, что не можете напрямую редактировать объект FileList по соображениям безопасности. Однако вы можете преобразовать его и отредактировать новый список в виде массива и позволить пользователям изменять файлы, которые они хотят загрузить.
Во-первых, давайте повторно используем шаблон из компонента MultipleFiles.vue:
Скрываем input
Первое, что мы сделаем, это скроем input. Для того чтобы сделать более простым дизайн интерфейса, чтобы пользователям было удобнее выбирать нужные им файлы. Для этого я просто добавил тег стиля, который убирает input с экрана.
Затем я добавил кнопку, которая вызывает щелчок на input:
Поэтому, когда мы кликаем на кнопке, мы запускаем клик на элементе input. Далее нам нужно реализовать метод addFiles() в нашем компоненте Vue следующим образом:
Это вызовет клик на input, и пользователю будет показано окно выбора файлов, где они смогут выбрать нужные файлы.
Реализация handleFilesUpload()
Здесь все становится немного иначе. С начало как и в первых двух примерах, мы добавим локальную переменную для добавления файлов:
Теперь, когда пользователь выбирает некоторые файлы для загрузки, мы помещаем их в нашу локальную переменную files:
Мы делаем это через цикл, а не помещаем весь кусок в массив files, потому что в противном случае у нас были бы группы, основанные на том, что было выбрано. Здесь вы также можете добавить проверки, чтобы пользователь не загружал один и тот же файл несколько раз.
Отображение загруженных файлов
В случае если мы хотим, чтобы пользователи могли удалить выбранные файлы, нам нужно отобразить загруженные в данный момент файлы.
Для этого мы вернемся к нашему шаблону и добавим следующий код:
Это делается для перебора всех файлов, которые мы добавили в данный момент, и отображения их пользователю.
Стоит отметить несколько вещей.
Далее мы добавляем метод removeFile(key), который удалит файл из массива файлов. Когда файл будет удален, реактивная природа VueJS обновит наш список.
Реализация метода removeFile()
Этот метод удалит файл из нашего массива загруженных файлов. Во-первых, давайте добавим метод в наш массив методов:
Метод принимает ключ из массива файлов указывающий на удаляемый файл. Полная реализация этого метода будет такая:
Отправка файлов на сервер
Далее отправим выбранные файлы на сервер для обработки.
Для этого добавим метод submitFiles() к нашему объекту methods:
Как и в остальных примерах, давайте сначала создадим наш объект FormData():
Теперь давайте добавим все выбранные файлы в данные формы formData:
Это перебирает файлы, которые выбрал пользователь, и подготавливает их для отправки на сервер.
Теперь мы можем запустить метод axios.post() для отправки файлов в нашу конечную точку:
Это отправляет все наши данные формы на сервер с файлами, которые пользователь загрузил! Если вы запустите это в качестве примера, вы увидите, что после удаления файла он больше не отправляется на сервер.
Наш компонент SelectFiles.vue должен выглядеть следующим образом:
Вот и все! Теперь вы можете разрешить пользователям исправлять свои ошибки, если они выберут файл, который не захотят загружать.
Несколько советов
Я бы хотел добавить еще несколько советов, на которые можно обратить внимание при загрузке с использованием FormData.
Добавление дополнительных данных в POST запрос
Вы всегда можете включить в свой POST запрос больше информации, чем простые файлы. Когда вы создаете свои FormData, вы можете добавить дополнительный текст или другие поля, например:
Поля first_name и last_name будут доступны на сервере, как обычный post запрос!
Массивы с FormData()
Теперь, поскольку мы настраиваем наш запрос перед отправкой на сервер, доступ к массивам осуществляется по-разному. Вам нужно будет учесть это при создании объекта FormData. В VueJS при работе с массивами вы не можете просто использовать:
так как вы получите [object Object] на стороне сервера. Вы можете либо перебирать свои данные и помещать их в специально организованный массив, либо вы можете использовать метод JSON.stringify() для данных, который преобразует их в JSON перед отправкой на сервер.
Вам просто нужно будет расшифровать его, прежде чем вы сможете получить к нему доступ. В PHP для этого есть метод json_decode($ json).
Очистка локальных файлов
Заключение
Надеюсь, эта статья немного поможет вам в реализация загрузки файлов с помощью VueJS и Axios через AJAX.
Функционал, отвечающий за отправку файлов на сервер, реализуется довольно просто. Как и в примерах из предыдущих уроков, за это отвечает специальное поле формы. Но ее настройка имеет некоторые особенности.
Если ваша форма содержит поля, отвечающие за загрузку файлов, то элементу
необходимо явным образом установить атрибут enctype в значение multipart/form-data , а method задать как POST .
Заметка
Приведенные выше значения атрибутов не связанны непосредственно с HTML. Они оптимизируют внутренние процессы браузера. Если вы правильным образом настроите элемент , отправка больших файлов будет произведена гораздо быстрее, а серверная программа сможет легко принять и обработать их.
Использование поля загрузки файлов
В HTML для отправки файлов из формы используется многозадачный элемент . Его атрибут type должен иметь значение file . Браузер отобразит такое поле в виде кнопки с текстом «выберите файл» или аналогичным.
При нажатии кнопки откроется проводник файловой системы. В нем можно перемещаться по директориям компьютера. Интерфейс интуитивно понятен любому пользователю. Все что нужно сделать — это найти нужный файл и нажать кнопку «Открыть». Отметим, что выбирать нужные документы и файлы может только сам пользователь. Явное указание атрибута value с именем или расположением какого-либо файла не приведет к успеху.
Чтобы выбранный файл был загружен при отправке формы, полю необходимо добавить атрибут name с уникальным значением.
Множественный выбор и блокировка поля
По умолчанию пользователь может выбрать только один файл, предназначенный к отправке. HTML позволяет изменить это поведение. Множественный выбор станет доступным после добавления к полю атрибута multiple .
Также нужно отметить, что поле загрузки файлов можно заблокировать с помощью атрибута disabled . Это сделает невозможным какое-либо взаимодействие с ним. Если оно заблокировано после осуществления выбора файла, он не будет отправлен вместе с остальными данными формы. Такая ситуация может возникнуть при использовании встроенного в браузер языка программирования JavaScript.
Принципы загрузки файлов
Любой загружаемый файл будет помещен в специальную директорию для временного хранения, а связанная с ним информация добавлена в суперглобальный массив $_FILES . Если не переместить файл в другое место, после завершения скрипта произойдет его бесследное удаление. Директория временного хранения определяется настройкой upload_tmp_dir конфигурационного файла php.ini .
Суперглобальный массив $_FILES
Если вместе с текущим запросом были загружены файлы, PHP-интерпретатор автоматически заполнит суперглобальный массив $_FILES соответствующей информацией. Его структура довольно проста. Элементы массива соответствуют именам параметров HTTP-запроса. Например, ваша веб-форма содержит поле загрузки файла с атрибутом « name="upload-file" ». В таком случае информация будет добавлена в $_FILES['upload-file'] .
Содержимое массива $_FILES:
Заметка
Существует одно требование к HTML-разметке полей, осуществляющих множественный выбор и загрузку файлов. Их атрибут name должен быть составлен следующим образом « name ». Если вы опустите конструкцию [] , PHP обработает только один файл.
Перемещение загруженного файла
Как говорилось выше, загружаемые файлы размещаются во временной директории сервера и автоматически удаляются PHP-интерпретатором после выполнения текущего запроса. Их можно сохранить, переместив в другое место. Использовать стандартные функции copy() или rename() крайне нежелательно.
Для перемещения загруженных файлов существует специальная функция move_uploaded_file() . Она принимает два обязательных строковых параметра. Первый указывает имя файла во временной директории, а второй - путь назначения. Функция возвращает true в случае успеха и false , если произошла ошибка.
С помощью функции is_uploaded_file() вы можете проверить, является ли файл загруженным в текущем запросе. Она принимает всего один параметр — имя файла, а возвращает результат логического типа.
Важно
PHP позволяет изменять местоположение загруженных файлов с помощью обычных функций копирования или перемещения. Однако это довольно опасно. Существует ряд ухищрённых атак, основанных на таком недальновидном подходе.
Для перемещения и проверки существования загруженных файлов всегда используйте функции move_uploaded_file() и is_uploaded_file() . В процессе выполнения они осуществляют расширенные проверки и автоматически отсеивают ряд распространенных атак.
Пример загрузки файла на сервер
Ниже приводится пример PHP-скрипта. Если он вызывается в первый раз, либо в текущем запросе отсутствует загрузка файла, пользователю выводится форма. При загрузке, файл перемещается в корневую директорию сайта, а пользователю показывается информация, связанная с ним. Обрабатываются только изображения в форматах jpg , jpeg и png .
Читайте также: