Upload File (Загрузка файла на сервер средствами Perl)


Оглавление (нажмите, чтобы открыть):

Загрузка файлов на сервер

Что такое Upload files, или почему не работает
copy («c:\images\sample.jpg», «https://mysite.ru/uploads/sample.jpg «)

Даже если у Вас в распоряжении всего один компьютер, на котором совмещен и сервер и рабочая станция, не стоит забывать о том, что php использует технологию клиент/сервер. Файл, который мы хотим загрузить, как правило, находится на машине клиента, т.е. пользователя, обыкновенного посетителя сайта. Место назначения — сервер. Для того чтобы совершить процесс передачи файла, нам понадобиться следующая форма:

При этом в поле action должен быть указан URL Вашего php-скрипта, который в дальнейшем будет заниматься обработкой загружаемых файлов. Скрытое поле MAX_FILE_SIZE должно предшествовать полю выбора файла, и содержать максимально допустимый размер файла в байтах. Его назначение — проверка размера файла еще до момента отправки файла на сервер. Это должно избавить пользователя от длительной и безрезультатной загрузки файла на сервер и образования лишнего трафика, но не стоит особо полагаться на это ограничение, так как его легко обойти.

Что происходит, когда пользователь выбрал файл на своем диске, и нажал на кнопку «Send file»? Браузер отсылает файл на сервер, где php-интерпретатор помещает его в свою временную директорию, присваивая ему случайное имя и выполняет скрипт, указанный в поле action.

Как должен выглядеть upload.php?

При написании скрипта, возникает естественный вопрос: как получить информацию о загруженном файле и достучаться до самого файла. Если Вы используете PHP версии 4.1.0 и старше, лучше всего будет обратиться к глобальному массиву $_FILES. Для каждого загруженного файла он содержит хеш-массив, со следующими данными:

  • $_FILES[‘userfile’][‘name’] — оригинальное имя файла, такое, каким его видел пользователь, выбирая файл;
  • $_FILES[‘userfile’][‘type’] — mime/type файла, к примеру, может быть image/gif; это поле полезно сохранить, если Вы хотите предоставлять интерфейс для скачивания загруженных файлов;
  • $_FILES[‘userfile’][‘size’] — размер загруженного файла;
  • $_FILES[‘userfile’][‘tmp_name’] — полный путь к временному файлу на диске;
  • $_FILES[‘userfile’][‘error’] — Начиная с версии 4.2.0, содержит код ошибки, который равен 0, если операция прошла успешно.

Для PHP версии ниже 4.1.0 этот массив называется $HTTP_POST_FILES. Не стоит забывать, что в отличие от $_FILES этот массив не является суперглобальным и при обращении к нему, к примеру, из функции, необходимо явно указывать global $HTTP_POST_FILES;

Если в настройках Вашего сервера register_globals=on, будут созданы дополнительные переменные вида $userfile_name, $userfile_type, $userfile_size… Учитывая, что, начиная с версии 4.2.0, в настройках по умолчанию register_globals=off использования этих переменных не рекомендовано, даже если они определены. Лучший способ получения информации о загружаемых файлах — использовать массив $_FILES.

Для работы с загруженными файлами лучше всего использовать встроенные функции is_uploaded_file() и move_uploaded_file(), которые проверяют, был ли загружен файл, и помещают его в указанную папку соответственно. Более детальную информацию Вы можете найти на страницах руководства. Не стоит изобретать велосипед и работать самому с временными файлами, копировать их, удалять. Это уже сделано до Вас и для Вас.

Настройка сервера

Я все сделал правильно, но у меня что-то не работает. Может, у меня неправильно сконфигурирован сервер?

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

В файле php.ini:

  • Если Вы хотите узнать, где расположен Ваш php.ini, выполните
  • file_uploads — возможность запретить или разрешить загрузку файлов в целом. По умолчанию On.
  • upload_max_filesize — максимальный размер файла, который может быть загружен. Если Вам необходимо работать с большими файлами, измените эту настройку. По умолчанию 2М. Не забудьте изменить post_max_size.
  • post_max_size — общее ограничение сверху на размер данных, передаваемых в POST запросе. Если Вам необходимо работать с большими файлами, или передавать несколько файлов одновременно, измените эту настройку. Значение по умолчанию 8М.
  • upload_tmp_dir — временная директория на сервере, в которую будут помещаться все загружаемые файлы. Проверьте, какие на нее выставлены права(если на данном этапе у Вас возникли сложности, смотрите пояснения в конце статьи). Такая директория должна существовать и у пользователя, под которым выполняется Apache, также должны быть права на запись в эту директорию. Если Вы работаете с включенным ограничением open_basedir — то временный каталог должен находиться внутри. Вам не нужно заботиться о ее чистке или об уникальности имен, PHP решает эту проблему за Вас.

В файле httpd.conf:

    Прежде всего, убедитесь, что Вы используете веб-сервер Apache 1.3 (последняя версия на момент написания статьи — 1.3.27). Если Вы используете Apache 2.0, Вам следует прочитать следующий отрывок из документации:

Do not use Apache 2.0 and PHP in a production environment neither on Unix nor on Windows.

  • Если Вы получили сообщение «POST Method Not Allowed», это означает, что надо искать что-то похожее на следующие директивы, и использовать ключевое слово Allow:
  • Проблемы с загрузкой бинарных файлов — классический вопрос «почему бьются файлы при upload». Вот способ решения, предложенный Димой Бородином (https://php.spb.ru): В директории, где лежит скрипт, делаем файл .htaccess, в котором пишем: В файл httpd.conf дописать строки:
  • Небольшие пояснения, к этому рецепту: вышеописанная проблема, когда загруженные на сервер архивы не распаковываются и картинки не отображаются, может возникать из-за того, что используется веб-сервер Russian Apache. Директива CharsetDisable отключает модуль charset-processing module, т.е. никакой перекодировки при скачивании файлов, находящихся в данной папке, происходить не будет. Директива CharsetRecodeMultipartForms выключает перекодировку данных, переданных методом POST с заголовком Content-Type: multipart/form-data. Т.е. двоичные данные, переданные с такой настройкой, будут оставлены в первоначальном виде, а все остальное наполнение сайта будет перекодировано согласно текущим настройкам сервера.

    Но при этом могут возникнуть осложнения: будьте готовы к тому, что в некоторых случаях текстовые части запросов вам придется перекодировать самостоятельно. Вот что по этому поводу говорится в документации:

    Используйте директиву CharsetRecodeMultipartForms, которая появилась в PL23, но при этом вам все-равно придется перекодировать вручную текстовые части запросов. Для этого можно использовать Russian Apache API, доступное в других модулях или Russian Apache Perl API, доступное из mod_perl.

    Один из примеров определения кодировки вы можете найти тут: https://tony2001.phpclub.net/detect_charset/detect.phps

    Самая свежая документация по Russian Apache находится на его официальном сайте: https://apache.lexa.ru/.

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

    Также возможна настройка параметров Apach с помощью .htaccess:

    Дополнительные возможности

    Загрузка нескольких файлов одновременно

    Пример формы загрузки нескольких файлов:

    И не забудьте увеличить post_max_size, если предполагается много файлов

    Автоматическая загрузка файлов на сервер

    Не стоит забывать, что файлы на диске пользователя — конфиденциальная информация, к которой ни JavaScript, ни уж тем более PHP не имеют ни малейшего отношения. До тех пор, пока пользователь сам не выбрал файл при помощи ни о какой работе с ним не может идти и речи. И не забывайте, что у данного поля ввода атрибут value защищен от записи.

    Хранение файлов в базе данных mySQL

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

    • Необходимо использовать поле типа BLOB
    • Перед тем, как класть в базу, не забыть применить к строке mysql_escape_string()
    • При отображении файла необходимо указывать заголовок content/type

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

    Хранение картинок в базе не является хорошем стилем. Гораздо удобней хранить в базе лишь пути к файлам изображений.

    Получение свойств изображения.

    Если перед вами возникла задача проверить тип или размеры картинки перед загрузкой файла на сервер, вам потребуется функция getimagesize(). В качестве аргумента она принимает имя файла на диске и возвращает массив, первые два элемента которого — ширина и высота соответственно, третий — тип изображения. В случае невозможности прочитать из указанного файла корректное изображение, функция возвращает ложь.

    Загрузка файлов, имеющих русско-язычное название

    При загрузке на сервер файлов, необходимо проверять их оригинальные имена на предмет наличия «нестандартных» символов (к примеру русских букв). В случае их присутствия необходимо произвести замену. Оригинальное имя файла можно найти в переменной $_FILES[‘userfile’][‘name’]. Как перекодировать русскоязычную строку в транслит можно можно найти в примерах PHP.

    Отображения статуса загрузки (Progress bar)

    Необходимо учитывать, что до полной загрузки файла, PHP не может оперировать ни размером файла, ни процентом его загрузки. Только когда файл уже находится на сервере PHP, то он получает возможность обращаться к информации. Если вам все-таки крайне необходимо реализовать такую возможность, воспользуйтесь Java-аплетом.

    Права на файлы

    Проблемы с правами на сервере (upload_tmp_dir)

    В Unix-подобных операционных системах каждой папке, файлу, ссылке выставлены соответствие права доступа. Они могут выглядеть как rwx-rw-r- или же как число 754.

    Доступность файла или каталога зависят от идентификатора пользователя и идентификатора группы, в которую он входит. Режим в целом описывается в терминах трех последовательностей, по три буквы в каждой:

    Здесь владелец, члены группы и все прочие пользователи обладают правами чтения файла, записи в него и его выполнения. Права — любая осмысленная комбинация следующих букв:

    r Право на чтение. (4)
    w Право на запись. (2)
    x Право на выполнение (поиск в каталоге). (1)

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

  • Установить владельцем каталога пользователя, с чьими привелегиями выполняется apache. Это можно узнать из файла httpd.conf или просмотрев список процессов на сервере. Права на каталог должны быть 700 (rwx——).
  • Независимо от того, кто является владельцем каталога, установить права 777 (rwxrwxrwx).

    Пример реализации загрузки картинок на сервер.

    Оригинал статьи находится на сайте PHP Club

    HTML5 Ajax upload очень больших файлов

    В этой небольшой заметке рассмотрен способ загрузки очень больших файлов (больше 2Гб) через браузер. Метод приведенный в этой заметке хорош тем что:

    • Файл загружается асинхронно. В это время на странице отображается индикатор загрузки (ProgressBar);
    • Файл загружается по частям и не считывается целиком в память ни сервером ни браузером клиента;
    • Браузер повторяет загрузку секции, если предыдущая попытка закончилась неудачно. Это очень полезное свойство при загрузке больших файлов по HTTP.
    Мастер Йода рекомендует:  Базовые инструменты Photoshop для новичков


    Плох этот методом тем, что требует использования браузера на базе Gecko 2.0 и выше или WebKit. На текущий момент, это такие браузеры как FireFox 4.0+, SeaMonkey 2.1+ или Google Chrome 11+.

    Основная идея

    Файл считывается по частям с помощью методов slice(), mozSlice() или webkitSlice() объекта Blob [2]. После этого, каждая часть отправляется на сервер с помощью sendAsBinary() объекта XMLHttpRequest [1]. Если часть по какой-то причине не загрузилась, то производится попытка загрузить часть снова.

    Стоит обратить внимание, что метод slice() объекта Blob устарел начиная с версии Gecko 2.0 (FireFox 4), метод mozSlice() добавлен в Gecko 5.0 (FireFox 5) и метод webkitSlice() добавлен Google Chrome 11.

    Еще в Google Chrome нет метода sendAsBinary() объекта XMLHttpRequest.

    fileuploader.js

    JavaScript код работает на стороне клиента (в браузере), считывает файл по частям и отправляет его на сервер.

    // Для начала определим метод XMLHttpRequest.sendAsBinary(),
    // если он не определен (Например, для браузера Google Chrome).

    if ( ! XMLHttpRequest. prototype . sendAsBinary ) <

    XMLHttpRequest. prototype . sendAsBinary = function ( datastr ) <
    function byteValue ( x ) <
    return x. charCodeAt ( 0 ) & 0xff ;
    >
    var ords = Array. prototype . map . call ( datastr , byteValue ) ;
    var ui8a = new Uint8Array ( ords ) ;
    this . send ( ui8a. buffer ) ;
    >
    >

    /**
    * Класс FileUploader.
    * @param ioptions Ассоциативный массив опций загрузки
    */
    function FileUploader ( ioptions ) <

    // Позиция, с которой будем загружать файл
    this . position = 0 ;

    // Размер загружаемого файла
    this . filesize = 0 ;

    // Объект Blob или File (FileList[i])
    this . file = null ;

    // Ассоциативный массив опций
    this . options = ioptions ;

    // Если не определена опция uploadscript, то возвращаем null. Нельзя
    // продолжать, если эта опция не определена.
    if ( this . options [ ‘uploadscript’ ] == undefined ) return null ;

    /*
    * Проверка, поддерживает ли браузер необходимые объекты
    * @return true, если браузер поддерживает все необходимые объекты
    */
    this . CheckBrowser = function ( ) <
    if ( window. File && window. FileReader && window. FileList && window. Blob ) return true ; else return false ;
    >

    /*
    * Загрузка части файла на сервер
    * @param from Позиция, с которой будем загружать файл
    */
    this . UploadPortion = function ( from ) <

    // Объект FileReader, в него будем считывать часть загружаемого файла
    var reader = new FileReader ( ) ;

    // Текущий объект
    var that = this ;

    // Позиция с которой будем загружать файл
    var loadfrom = from ;

    // Объект Blob, для частичного считывания файла
    var blob = null ;

    // Таймаут для функции setTimeout. С помощью этой функции реализована повторная попытка загрузки
    // по таймауту (что не совсем корректно)
    var xhrHttpTimeout = null ;

    /*
    * Событие срабатывающее после чтения части файла в FileReader
    * @param evt Событие
    */
    reader. onloadend = function ( evt ) <
    if ( evt. target . readyState == FileReader. DONE ) <

    // Создадим объект XMLHttpRequest, установим адрес скрипта для POST
    // и необходимые заголовки HTTP запроса.
    var xhr = new XMLHttpRequest ( ) ;
    xhr. open ( ‘POST’ , that. options [ ‘uploadscript’ ] , true ) ;
    xhr. setRequestHeader ( «Content-Type» , «application/x-binary; charset=x-user-defined» ) ;

    // Идентификатор загрузки (чтобы знать на стороне сервера что с чем склеивать)
    xhr. setRequestHeader ( «Upload-Id» , that. options [ ‘uploadid’ ] ) ;
    // Позиция начала в файле
    xhr. setRequestHeader ( «Portion-From» , from ) ;
    // Размер порции
    xhr. setRequestHeader ( «Portion-Size» , that. options [ ‘portion’ ] ) ;

    // Установим таймаут
    that. xhrHttpTimeout = setTimeout ( function ( ) <
    xhr. abort ( ) ;
    > , that. options [ ‘timeout’ ] ) ;

    /*
    * Событие XMLHttpRequest.onProcess. Отрисовка ProgressBar.
    * @param evt Событие
    */
    xhr. upload . addEventListener ( «progress» , function ( evt ) <
    if ( evt. lengthComputable ) <

    // Посчитаем количество закаченного в процентах (с точность до 0.1)
    var percentComplete = Math. round ( ( loadfrom + evt. loaded ) * 1000 / that. filesize ) ; percentComplete /= 10 ;

    // Посчитаем ширину синей полоски ProgressBar
    var w >= Math. round ( ( loadfrom + evt. loaded ) * 300 / that. filesize ) ;

    // Изменим свойства элементом ProgressBar’а, добавим к нему текст
    var div1 = document. getElementById ( ‘cnuploader_progressbar’ ) ;
    var div2 = document. getElementById ( ‘cnuploader_progresscomplete’ ) ;

    div1. style . display = ‘block’ ;
    div2. style . display = ‘block’ ;
    div2. style . width = w >+ ‘px’ ;
    if ( percentComplete 30 ) <
    div2. textContent = » ;
    div1. textContent = percentComplete + ‘%’ ;
    >
    else <
    div2. textContent = percentComplete + ‘%’ ;
    div1. textContent = » ;
    >
    >

    /*
    * Событие XMLHttpRequest.onLoad. Окончание загрузки порции.
    * @param evt Событие
    */
    xhr. addEventListener ( «load» , function ( evt ) <

    // Очистим таймаут
    clearTimeout ( that. xhrHttpTimeout ) ;

    // Если сервер не вернул HTTP статус 200, то выведем окно с сообщением сервера.
    if ( evt. target . status != 200 ) <
    alert ( evt. target . responseText ) ;
    return ;
    >

    // Добавим к текущей позиции размер порции.
    that. position += that. options [ ‘portion’ ] ;

    // Закачаем следующую порцию, если файл еще не кончился.
    if ( that. filesize > that. position ) <
    that. UploadPortion ( that. position ) ;
    >
    else <
    // Если все порции загружены, сообщим об этом серверу. XMLHttpRequest, метод GET,
    // PHP скрипт тот-же.
    var gxhr = new XMLHttpRequest ( ) ;
    gxhr. open ( ‘GET’ , that. options [ ‘uploadscript’ ] + ‘?action=done’ , true ) ;

    // Установим идентификатор загруки.
    gxhr. setRequestHeader ( «Upload-Id» , that. options [ ‘uploadid’ ] ) ;

    /*
    * Событие XMLHttpRequest.onLoad. Окончание загрузки сообщения об окончании загрузки файла :).
    * @param evt Событие
    */
    gxhr. addEventListener ( «load» , function ( evt ) <

    // Если сервер не вернул HTTP статус 200, то выведем окно с сообщением сервера.
    if ( evt. target . status != 200 ) <
    alert ( evt. target . responseText . toString ( ) ) ;
    return ;
    >
    // Если все нормально, то отправим пользователя дальше. Там может быть сообщение
    // об успешной загрузке или следующий шаг формы с дополнительным полями.
    else window. parent . location = that. options [ ‘redirect_success’ ] ;
    > , false ) ;

    // Отправим HTTP GET запрос
    gxhr. sendAsBinary ( » ) ;
    >
    > , false ) ;

    /*
    * Событие XMLHttpRequest.onError. Ошибка при загрузке
    * @param evt Событие
    */
    xhr. addEventListener ( «error» , function ( evt ) <

    // Очистим таймаут
    clearTimeout ( that. xhrHttpTimeout ) ;

    // Сообщим серверу об ошибке во время загруке, сервер сможет удалить уже загруженные части.
    // XMLHttpRequest, метод GET, PHP скрипт тот-же.
    var gxhr = new XMLHttpRequest ( ) ;

    gxhr. open ( ‘GET’ , that. options [ ‘uploadscript’ ] + ‘?action=abort’ , true ) ;

    // Установим идентификатор загруки.
    gxhr. setRequestHeader ( «Upload-Id» , that. options [ ‘uploadid’ ] ) ;

    /*
    * Событие XMLHttpRequest.onLoad. Окончание загрузки сообщения об ошибке загрузки :).
    * @param evt Событие
    */
    gxhr. addEventListener ( «load» , function ( evt ) <

    // Если сервер не вернул HTTP статус 200, то выведем окно с сообщением сервера.
    if ( evt. target . status != 200 ) <
    alert ( evt. target . responseText ) ;
    return ;
    >
    > , false ) ;

    // Отправим HTTP GET запрос
    gxhr. sendAsBinary ( » ) ;

    // Отобразим сообщение об ошибке
    if ( that. options [ ‘message_error’ ] == undefined ) alert ( «There was an error attempting to upload the file.» ) ; else alert ( that. options [ ‘message_error’ ] ) ;
    > , false ) ;

    /*
    * Событие XMLHttpRequest.onAbort. Если по какой-то причине передача прервана, повторим попытку.
    * @param evt Событие
    */
    xhr. addEventListener ( «abort» , function ( evt ) <
    clearTimeout ( that. xhrHttpTimeout ) ;
    that. UploadPortion ( that. position ) ;
    > , false ) ;

    // Отправим порцию методом POST
    xhr. sendAsBinary ( evt. target . result ) ;
    >
    > ;

    that. blob = null ;

    // Считаем порцию в объект Blob. Три условия для трех возможных определений Blob.[.*]slice().
    if ( this . file . slice ) that. blob = this . file . slice ( from , from + that. options [ ‘portion’ ] ) ;
    else <
    if ( this . file . webkitSlice ) that. blob = this . file . webkitSlice ( from , from + that. options [ ‘portion’ ] ) ;
    else <
    if ( this . file . mozSlice ) that. blob = this . file . mozSlice ( from , from + that. options [ ‘portion’ ] ) ;
    >
    >

    // Считаем Blob (часть файла) в FileReader
    reader. readAsBinaryString ( that. blob ) ;
    >

    /*
    * Загрузка файла на сервер
    * return Число. Если не 0, то произошла ошибка
    */
    this . Upload = function ( ) <

    // Скроем форму, чтобы пользователь не отправил файл дважды
    var e = document. getElementById ( this . options [ ‘form’ ] ) ;
    if ( e ) e. style . display = ‘none’ ;

    if ( ! this . file ) return — 1 ;
    else <

    // Если размер файла больше размера порциии ограничимся одной порцией
    if ( this . filesize > this . options [ ‘portion’ ] ) this . UploadPortion ( 0 , this . options [ ‘portion’ ] ) ;

    // Иначе отправим файл целиком
    else this . UploadPortion ( 0 , this . filesize ) ;
    >
    >

    if ( this . CheckBrowser ( ) ) <


    // Установим значения по умолчанию
    if ( this . options [ ‘portion’ ] == undefined ) this . options [ ‘portion’ ] = 1048576 ;
    if ( this . options [ ‘timeout’ ] == undefined ) this . options [ ‘timeout’ ] = 15000 ;

    // Добавим обработку события выбора файла
    document. getElementById ( this . options [ ‘formfiles’ ] ) . addEventListener ( ‘change’ , function ( evt ) <

    var files = evt. target . files ;

    // Выберем только первый файл
    for ( var i = 0 , f ; f = files [ i ] ; i ++ ) <
    that. filesize = f. size ;
    that. file = f ;
    break ;
    >
    > , false ) ;

    // Добавим обработку события onSubmit формы
    document. getElementById ( this . options [ ‘form’ ] ) . addEventListener ( ‘submit’ , function ( evt ) <
    that. Upload ( ) ;
    ( arguments [ 0 ] . preventDefault ) ? arguments [ 0 ] . preventDefault ( ) : arguments [ 0 ] . returnValue = false ;
    > , false ) ;
    >

    upload.php

    PHP скрипт, работает на стороне сервера. Его задача — принимать и склеивать порции. После окончания передачи всех порций скрипт переименовывает файл и создает флаг сигнализирующий о том что файл готов к обработке. В моем случае отдельный демон проверяет этот флаг и берет файлы «в оборот».

    // Каталог в который будет загружаться файл
    $uploaddir = «./uploaddir» ;

    // Идентификатор загрузки (аплоада). Для генерации идентификатора я обычно использую функцию md5()
    $hash = $_SERVER [ «HTTP_UPLOAD_ID» ] ;

    // Информацию о ходе загрузки сохраним в системный лог, это позволить решать проблемы оперативнее
    openlog ( «html5upload.php» , LOG_P >| LOG_PERROR , LOG_LOCAL0 ) ;

    // Проверим корректность идентификатора
    if ( preg_match ( «/^[0123456789abcdef]<32>$/i» , $hash ) ) <

    // Если HTTP запрос сделан методом GET, то это не загрузка порции, а пост-обработка
    if ( $_SERVER [ «REQUEST_METHOD» ] == «GET» ) <

    // abort — сотрем загружаемый файл. Загрузка не удалась.
    if ( $_GET [ «action» ] == «abort» ) <
    if ( is_file ( $uploaddir . «/» . $hash . «.html5upload» ) ) unlink ( $uploaddir . «/» . $hash . «.html5upload» ) ;
    print «ok abort» ;
    return ;
    >

    // done — загрузка завершена успешно. Переименуем файл и создадим файл-флаг.
    if ( $_GET [ «action» ] == «done» ) <
    syslog ( LOG_INFO , «Finished for hash » . $hash ) ;

    // Если файл существует, то удалим его
    if ( is_file ( $uploaddir . «/» . $hash . «.original» ) ) unlink ( $uploaddir . «/» . $hash . «.original» ) ;

    // Переименуем загружаемый файл
    rename ( $uploaddir . «/» . $hash . «.html5upload» , $uploaddir . «/» . $hash . «.original» ) ;

    // Создадим файл-флаг
    $fw = fopen ( $uploaddir . «/» . $hash . «.original_ready» , «wb» ) ; if ( $fw ) fclose ( $fw ) ;
    >
    >

    // Если HTTP запрос сделан методом POST, то это загрузка порции
    elseif ( $_SERVER [ «REQUEST_METHOD» ] == «POST» ) <

    syslog ( LOG_INFO , «Uploading chunk. Hash » . $hash . » (» . intval ( $_SERVER [ «HTTP_PORTION_FROM» ] ) . «-» . intval ( $_SERVER [ «HTTP_PORTION_FROM» ] + $_SERVER [ «HTTP_PORTION_SIZE» ] ) . «, size: » . intval ( $_SERVER [ «HTTP_PORTION_SIZE» ] ) . «)» ) ;

    // Имя файла получим из идентификатора загрузки
    $filename = $uploaddir . «/» . $hash . «.html5upload» ;

    // Если загружается первая порция, то откроем файл для записи, если не первая, то для дозаписи.
    if ( intval ( $_SERVER [ «HTTP_PORTION_FROM» ] ) == 0 )
    $fout = fopen ( $filename , «wb» ) ;
    else
    $fout = fopen ( $filename , «ab» ) ;

    // Если не смогли открыть файл на запись, то выдаем сообщение об ошибке
    if ( ! $fout ) <
    syslog ( LOG_INFO , «Can’t open file for writing: » . $filename ) ;
    header ( «HTTP/1.0 500 Internal Server Error» ) ;
    print «Can’t open file for writing.» ;
    return ;
    >

    // Из stdin читаем данные отправленные методом POST — это и есть содержимое порций
    $fin = fopen ( «php://input» , «rb» ) ;
    if ( $fin ) <
    while ( ! feof ( $fin ) ) <
    // Считаем 1Мб из stdin
    $data = fread ( $fin , 1024 * 1024 ) ;
    // Сохраним считанные данные в файл
    fwrite ( $fout , $data ) ;
    >
    fclose ( $fin ) ;
    >

    // Все нормально, вернем HTTP 200 и тело ответа «ok»
    header ( «HTTP/1.0 200 OK» ) ;
    print «ok \n » ;
    >
    else <
    // Если неверный идентификатор загрузку, то вернем HTTP 500 и сообщение об ошибке
    syslog ( LOG_INFO , «Uploading chunk. Wrong hash » . $hash ) ;
    header ( «HTTP/1.0 500 Internal Server Error» ) ;
    print «Wrong session hash.» ;
    >

    Мастер Йода рекомендует:  5 песен для программистов

    // Закроем syslog лог
    closelog ( ) ;

    index.php

    Файл с HTML формой и инициализацией скрипта загрузки.

    Заголовок HTML документа. Здесь, для примера, подменен идентификатор загрузки. Вы можете генерировать его на свое усмотрение.

    Таблица стилей для индикатора прогресса (PorgressBar)

    Подключение класса загрузки. Антикеш на всякий случай.

    Форма загрузки. Изначально она скрыта, отображается только после успешной инициализации объекта-загрузчика.

    / head >
    body onload = «ShowForm();» >
    div >

    p > Максимальный размер файла при загрузке через браузер — b > 4Гб / b > . / p >

    form action = «./» method = «post» id = «uploadform» onsubmit = «return false;» style = «display:none;» >

    table cellspacing = 1 >
    tr > td > div id = «message» > Выберите файл: / div > / td > td > input type = «file» id = «files» name = «files[]» / > / td > / t>
    / table >
    input type = «submit» value = «Загрузить >>» / >

    Индикатор прогресса (PorgressBar) и подсказки

    div id = «cnuploader_progressbar» > / div >
    div id = «cnuploader_progresscomplete» > / div >

    p > Вы сможете добавить название и описание после того как видео будет загружено на сервер. / p >

    p > Мы принимаем видео, не нарушающее требования российского законодательства (не содержащее порнографию, ненормативную лексику, призыв к насилию и т.д.) и не содержащее рекламу. / p >

    p > Используется загрузчик HTML5 / p >

    script type = «text/javascript» >

    // Создаем объект — FileUploader. Задаем опции.
    var uploader = new FileUploader ( <

    // Сообщение об ошибке
    message_error : ‘Ошибка при загрузке файла’ ,

    // ID элемента формы
    form : ‘uploadform’ ,

    // Идентификатор загрузки. В нашему случе хэш.
    upload >: ‘ ‘ ,

    // URL скрипта загрузки (описан выше).
    uploadscript : ‘./upload.php’ ,

    // URL, куда перенаправить пользователя при успешной загрузке
    redirect_success : ‘./step2.php?hash= ‘ ,

    // URL, куда отправить пользователя при ошибке загрузки
    redirect_abort : ‘./abort.php?hash= ‘ ,

    // Размер порции. 2 Мб
    portion : 1024 * 1024 * 2
    > ) ;

    Загрузка файлов на сервер PHP

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

    HTML-форма отправит файл только методом POST и с атрибутом enctype=»multipart/form-data» .

    Форма для загрузки сразу нескольких файлов

    Файл upload.php

    • Поддерживает как одиночную загрузку файла так и множественную (multiple) без изменения кода.
    • Проверка на все возможные ошибки которые могут возникнуть при загрузке файлов.
    • Имена файлов переводятся в транслит и удаляются символы которые будут в дальнейшем мешать вывести их на сайте.
    • Есть возможность указать разрешенные и запрещенные для загрузки расширения файлов.

    Возможные проблемы


    • На unix хостингах php функция move_uploaded_file() не будут перемещать файлы в директорию если у нее права меньше 777.
    • Загрузка файлов может быть отключена в настройках PHP директивой file_uploads .
    • Не загружаются файлы большого размера, причина в ограничениях хостинга.
      Посмотрите в phpinfo() значения директив:
      • upload_max_filesize – максимальный размер закачиваемого файла.
      • max_file_uploads – максимальное количество одновременно закачиваемых файлов.
      • post_max_size – максимально допустимый размер данных, отправляемых методом POST, его значение должно быть больше upload_max_filesize .
      • memory_limit – значение должно быть больше чем post_max_size .

    Не забудьте в директории куда помещаются загруженные файлы запретить выполнение PHP.

    Программирование для Веб: Загрузка файлов на сервер и посылка e-mail с вложениями

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

    Для использования скрипта нужно установить 2 модуля: MIME::Lite и CGI

    Второй скорее всего у вас есть, а первый необходимо скачать. Документацию по CGI.pm можно посмотреть здесь

    Приступим к разбору листинга:

    Строчки с первой по третью не делают ничего очень важного. Первая – стандартное начало любого скрипта, вторая и третья – по вкусу.

    5-12 строки – конфигурация скрипта:

    Cтроки 7,8,9 – параметры письма (соответственно от кого, к кому и тема)

    Cтрока 10 – значение INCLUDE_META, которое если равно 1, то в письмо включается еще одно вложение с различной служебной информацией: о загруженном файле, переменных окружения и т.д.

    Строка 14 – подключение модуля CGI.pm. Здесь не используется объектно-ориентированный интерфейс, а просто импортируются все функции.

    16 строка – получение переданных браузером параметров, если они есть. Если в процессе закачки файла возникнет ошибка, то скрипт сразу прервет свою работу и сообщит об ошибке (cgi_error()). При проверке в Perl 5.0 под Windows я столкнулся с ошибкой – обругали меня за то, что функции cgi_error() нет. Пришлось сходить на CPAN.org и взять новую версию CGI.pm (в моем случае это была версия 2.74)

    Строки с 22 по 37 выводят форму для загрузки файла. Форма объявляется как multipart, в HTML-виде это выглядит так: enctype=»multipart/form-data». Строка 29 – специальное поле для загрузки файла, в браузере оно отображается с кнопочкой «Обзор» (или “Browse”) справа.

    Строки 30 и 31 предлагают пользователю определить, как будет передаваться файл – как текст (mime-тип: quoted-printable) или как бинарник (тип: base64)

    Форма закончилась – начался разбор параметров. Если скрипт вызывается первый раз – то здесь его работа закончится, а если пользователь нажимает кнопку Upload – то далее идет обработка:

    Строка 40 – подключение модуля MIME::Lite

    Строка 41 и 42 – получение файла, который пользователь загрузил и информации о нем в переменные $file и $info. $file в зависимости от контекста — и файл, и строка.

    Строки 43-45 создают объект-письмо $msg. Ему присваиваются поля «от кого», «кому» и «тема» — ведь письмо должно куда-то придти.

    Если включен конфигурационный параметр INCLUDE_META – строки с 46 по 56 создают первое вложение в письмо, содержащее служебную информацию. Если вдруг в этой служебной информации будут русские буквы – то лучше Encoding поменять на 8bit.

    Строки 57-65 выполняют основную работу – создают вложение-файл, закачанный пользователем. 58-60 строки – выбор типа вложения, в зависимости от того, который был указан в форме.

    Ну и последние строчки скрипта – с 66 по 74 – отправляют сообщение по почте. Здесь используется метод send_by_smtp(), он более универсален, однако использует модуль Net::SMTP. Можно также использовать send_by_sendmail() (тогда sendmail будет искаться в /usr/lib/, что можно поменять, передав параметр Sendmail=>…, подробнее смотрите в модуле MIME::Lite)

    А если при передаче произошла ошибка при отправке письма – то скрипт просто выдаст пользователю на страницу все что должен был отправить по почте.

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

    Загрузка файла(ов) на сервер из формы средствами PHP

    Сегодня загрузка файлов является практически неотъемлемым атрибутом современного web приложения. В данной статье речь пойдёт о том, как же загрузить файл(ы) на сервер с помощью PHP.

    Навигация по статье:

    Настройка php.ini

    Конфигурационный файл php.ini необходимо настраивать согласно бизнес-логики проекта! Например, мы планируем загружать не более десяти файлов до 2 Мбайт, а это значит нам понадобиться

    Загрузка одного файла на сервер из формы

    Для начала разберём механизм загрузки одной картинки на сервер. Для загрузки картинки с компьютера пользователя необходимо с помощью HTML-формы отправить нужный (выбранный) файл PHP-скрипту upload.php методом POST и указать способ кодирования данных enctype=»multipart/form-data» (в данном случае данные не кодируются и это значение применяется только для отправки бинарных файлов).

    После отправки файла PHP-скрипту upload.php его можно перехватить с помощью суперглобальной переменной $_FILES с таким же именем, которая в массиве содержит информацию о файле (в нашем случае image ):

    Не всем данным из $_FILES можно доверять: MIME-тип и размер файла можно подделать, т. к. они формируются из HTTP-ответа, а расширению в имени файла не стоит доверять в силу того, что за ним может скрываться совершенно другой файл. Тем не менее, дальше нам нужно проверить корректно ли загрузился наш файл и загрузился ли он вообще. Для этого необходимо проверить ошибки в $_FILES[‘image’][‘error’] и удостовериться, что файл загружен методом POST с помощью функции is_uploaded_file() . Если что-то идёт не по плану, значит выводим ошибку на экран:

    Для того, чтобы «редиска» не загрузил вредоносный код, встроенный в изображение, нельзя доверять функции getimagesize() , которая также возвращает MIME-тип. Функция ожидает, что первый аргумент является ссылкой на корректный файл изображения. Определить настоящий MIME-тип картинки можно через расширение FileInfo . Код ниже проверит наличие ключевого слова image в типе нашего загружаемого файла и если его не окажется, выдаст ошибку:

    Таким образом, при необходимости, делаем проверку и на другие MIME-типы. Например, для zip архивов проверка будет такая:

    На данном этапе мы уже можем загружать абсолютно любые картинки на наш сервер, прошедшие проверку на MIME-тип, но для загрузки изображений по определённым характеристикам нам необходимо валидировать их с помощью функции getimagesize() , которой отдадим сам бинарный файл $_FILES[‘image’][‘tmp_name’] . В результате мы получим массив из элементов:

    Для дальнейшей валидации изображения и работы над ним нам необходимо знать только 3 значения: ширину, высоту и размер файла (для вычисления размера применим функцию filesize() для бинарного файла из временной папки).

    После всех проверок мы можем с уверенностью переместить наш загружаемый файл в какую-нибудь директорию с картинками. Делать лучше это через функцию move_uploaded_file(), которая работает в безопасном режиме. Перед перемещением файла нельзя забыть сгенерировать случайное имя и расширение из типа изображения для нашего файла. Вот так это выглядит:

    Вместо простого способа генерации имени файла на основе MD5-хеша можно пойти более продвинутым путём, а именно написать отдельную функцию, которая будет проверять уникальность названия картинки для того, чтобы случайно не перезаписать уже загруженный файл. Если такого названия ещё нет, функция сгенерирует его. Такая проблема появляется в больших проектах и с большим количеством картинок. Но всё же)

    Генерация имени для картинки теперь будет такой:

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

    Загрузка нескольких файлов на сервер из формы

    Разберём механизм загрузки нескольких изображений за один раз с локальной машины пользователя. Продолжим дальше работать с $_FILES . Наша новая HTML-форма будет немного отличаться от старой.

    Как видно в конец имени поля выбора файла name=»images[]» добавились фигурные скобки и атрибут multiple , который разрешает браузеру выбрать несколько файлов. Все файлы снова загрузятся во временную папку, если не будет никаких ошибок в php.ini . Перехватить их можно в $_FILES , но на этот раз суперглобальная переменная будет иметь неудобную структуру для обработки данных в массиве. Решается эта задача небольшими манипуляциями с массивом:

    Мы реализовали механизм загрузки нескольких файлов на сервер. Весь код целиком лежит здесь .

    Загрузка файла на сервер в PHP

    Я в PHP не особо силен, но пролистав несколько страниц гугла я понял что моя ситуация не типичная.

    Мне нужно с помощью скрипта загрузить файл на сервер. Для этого я нашел в интернете очень простой html-файл:

    и такой же простой скрипт:

    Как и следовало ожидать — файл не загружается. Вся проблема в том, что в $_FILES[«file»][«error»] ничего не содержится. После «загрузки» массив $_FILES имеет следующий вид:

    Мастер Йода рекомендует:  8 лучших YouTube-каналов для изучения Java

    post_max_size = 8M
    file_uploads = On
    upload_max_filesize = 2M

    и т.д., все в общем учтено и все выставлено как нужно.

    Картинку я загружаю именно нормальную JPEG, с расширением jpg. Впрочем, даже когда я вообще убираю все эти проверки на тип файла — все равно все то же самое происходит. Пробовал на разных браузерах. Скрипт крутится на моем instance на amazon aws ec2 под управлением SuSE Linux, Apache2.

    Загрузка файлов на сайт: PHP, AJAX, HTML5 и Drag’n’Drop

    Скучные формы загрузки — прошлый век. HTML5 дает возможности, чтобы добавить Drag’n’Drop, а AJAX позволяет загружать файлы без обновления страницы.

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


    Программисту нужно позаботиться о том, чтобы посетитель смог сделать это максимально удобно. Загрузить файл на сайт можно и с помощью обычной формы и обработчика на PHP, но с выходом HTML5 появились другие интересные возможности — в этой статье мы поговорим и о базовых функциях, и о нововведениях.

    Загрузка файлов на сервер путем перетаскивания. Часть 1

    Дата публикации: 2015-06-17

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

    Введение

    Загрузка фалов на сервер, достаточно распространенная задача в сайтостроении, и в большинстве случаев она решается путем добавления на страницу стандартного поля формы file:

    Как создать сайт самому?

    Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

    Но использование данного поля не всегда удобно, да и его стандартный дизайн, не всегда совместим с дизайном веб-страниц. В данное время, очень популярны загрузки на сервер путем перетаскивания фалов в специально отведенную область сайта. Примером может служить сайт https://disk.yandex.ru:

    В данном уроке мы с Вами начнем создавать механизм загрузки файлов на сервер путем перетаскивания, и поможет нам в этом один из виджетов библиотеки Formstone – Upload, который как раз разработан для этих целей (официальный сайт библиотеки https://formstone.it/).

    Виджет Upload

    Итак, на тестовой странице удаляем элемент формы file и вместо него располагаем обычный блок

    Полный код тестовой страницы:

    Обратите внимание, на данной странице уже подключена библиотека jQuery и ядро библиотеки Formstone. Далее подключаем виджет и его файл стилей (в файловой структуре тестовой страницы уже содержатся данные элементы).

    Теперь необходимо, при помощи библиотеки jQuery выбрать блок, который служит областью приема файлов и вызвать метод upload():

    Теперь давайте перейдем в браузер и посмотрим, что изменилось:

    Как создать сайт самому?

    Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

    Как Вы видите, внешний вид приемного блока изменен, теперь если перетащить файл, или несколько файлов в данный блок будет выполнена асинхронная (методом AJAX) отправка элементов на сервер. Но при этом виджет Upload не сохраняет фалы на сервере, он только собирает информацию о тех файлах которые необходимо отправить и, используя метод AJAX отправляет запрос (запрос типа POST) на сервер с необходимыми заголовками. В этом мы можем убедиться, если посмотрим консоль JavaScript:

    Теперь необходимо указать некоторые настройки:

    Основные настройки виджета:

    action – файл на сервере, который обработает переданные данные(сохранит файл на сервере);

    label – строка которая отображается в приемнике файлов;

    postKey – имя поля в запросе;

    maxQueue — максимальное количество одновременно отправляемых запросов;

    maxSize – максимальный размер передаваемого файла;

    postData — дополнительные данные, которые будут переданы POST запросом на сервер.

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

    Скрипт обработчик.

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

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

    Обратите внимание, что если к данному файлу мы обращаемся асинхронно, то весь вывод на экран, будет возвращен в качестве ответа от сервера. Поэтому если файл загружен, мы будем возвращать ‘OK’, в противном же случае — ‘ERROR’. Теперь давайте протестируем наш скрипт:

    После перемещения файла в область загрузки, в консоли JavaScript мы видим, что файл был передан и в качестве ответа, была возвращена строка OK. При этом в папке uploads, появился новый сохраненный файл.

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

    Всего Вам доброго и удачного кодирования.

    Как создать сайт самому?

    Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

    Разработка веб-приложения на PHP

    Создайте веб-приложение на PHP на примере приема платежей на сайте

    Uploading Files Using CGI and Perl Article

    Would you like to give your visitors the ability to upload files to your site? Letting them upload content with their Web browsers can be very useful, and fun too! You can let them contribute pictures, sounds and other binary files to your site. And you can use a file upload facility on your own Website to update your site’s content easily via your own Web browser.

    If you’ve ever used a Web-based email service such as Yahoo! Mail or Hotmail, you’ve probably sent email with attachments. To add attachments to your emails, you simply click the “Browse…” button on the Web page to select the file from your hard drive, and then your browser sends the file to the server. This is file upload in action!

    But how does it work? In this article, which has been updated from an earlier version I wrote a few years ago, I’m going to talk you through the process of file upload, and show you how to build a simple file upload example using CGI and Perl — that’s right, Perl! Despite the hype over other scripting languages, Perl is still a powerful and popular choice to power a web site. The example we’ll go through will allow people to upload photos of themselves to your Web server.

    What You’ll Need

    To build your own file upload script, you’ll need the following:

    • Access to a Web server that supports CGI (nearly all do)
    • A copy of Perl running on the Web server
    • The Perl CGI library, CGI.pm, installed on your Web server. This is probably pre-installed, but if it’s not, you can grab it here.
    How Does It Work?

    File upload works by using a special type of form field called “file”, and a special type of form encoding called “multipart/form-data”. The file form field displays a text box for the filename of the file to upload, and a “Browse…” button:

    The user clicks the “Browse…” button to bring up the file selector, and chooses the file they wish to upload. Then, when they click the “Submit” button on the form, the file’s data is uploaded to the Web server, along with the rest of the form’s data:

    At the Web server end, the software (in our case, a CGI script) interprets the form data that’s sent from the browser, and extracts the file name and contents, along with the other form fields. Usually, the file is then saved to a directory on the server.

    Now, let’s create a file upload form that allows your users to upload files to your Web server.

    1. The “form” Element

    The first part of a file upload form is the “form” element:

    Как я могу получить размер файла в Perl перед обработкой запроса на загрузку?

    Я хочу получить размер файла. Я делаю это:

    Но он не работает. Обратите внимание, что я не загружал файл. Я хочу проверить его размер перед его загрузкой. Поэтому, чтобы ограничить его до 1 МБ.

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

    Поскольку вы, похоже, работаете под простым CGI, вы должны иметь возможность получить длину тела запроса в $ENV .

    Также хочу проверить здравомыслие, возможно, уже имея постмакс-набор (из perldoc CGI):

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

    Загруженный файл спрятан в месте tmp на сервере при отправке формы, проверьте размер файла.

    Поставьте значение для поля $.

    Это не имеет ничего общего с Perl.

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

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

    Лучше всего позволить пользователю начать загрузку и прервать, если файл слишком большой.

    Если вы хотите проверить, прежде чем обрабатывать запрос, вам может быть лучше проверить веб-страницу, которая вызывает запрос. Я не думаю, что веб-браузер может сделать это сам, но если вы не возражаете против Flash, есть много инструментов для загрузки Flash, которые могут проверять такие вещи, как размер (а также типы файлов) и предотвращать загрузку.

    Очевидно, что вы также захотите проверить на стороне сервера, но к тому времени, когда пользователь начал отправлять запрос на сервер, вы уже используете свои циклы процессора и пропускную способность.

  • Добавить комментарий