Предисловие
Раньше я об этом не задумывался и пользовался готовым решением типа от Drupal для отдачи файлов и более мне не надо было. Пока несколько месяцев назад у меня не возникла острая необходимость не только отдавать файлы.
В интернете есть много информации о том как скачивать файлы с сервера и загружать файлы на сервер, а также между серверами. Но нигде нет простого решения которое было бы более ли менее универсально.
Я несколько дней убил на изучение всяких заголовков и вариаций использования cUrl, но собрать все воедино не выходило. Видел много разных подобных классов, но везде было либо частичное решение, либо очень запутанно, либо и то, и другое.
И лишь благодаря единичным статьям, кусочкам информации с форумов и всяким комментариям удалось собрать пазл воедино. Я не утверждаю что мое решение полностью универсально, но очень удобное во многих случаях, хотя это вам решать.
Если у кого-либо возникнет желание улучшить мое решение этого вопроса и хватает знаний в этом направлении, то я буду рад, если вы сделаете какие-либо исправления или добавления к коду который лежит в открытом доступе на GitHub.
А теперь к делу, функции класса CargaDes:
- Отдача файла через браузер без показа его места хранения и с возможностью докачки;
- Загрузка файла на сервер через браузер с индикатором прогресса;
- Скачивание файлов с удаленного сервера на свой сервер с индикатором прогресса;
- Загрузка файлов со своего сервера на удаленный сервер с индикатором прогресса.
Для начала нужно скачать и подключить класс CargaDes:
1. Отдача файла через браузер без показа его места хранения с возможностью докачки и регулирования скорости
$realFilePath = dirname( __FILE__ ) . '/file.zip';//Полный путь к отдаваемому файлу
Этот метод очень похож на Drupal и иже с ним:
$CargaDes = new CargaDes;
$client_d = new ClientD($realFilePath);
//Не обязательные аргументы
$client_d->erroff = false;//True отключает вывод ошибок
$client_d->lang = 'ru';
$client_d->speed = 25;// это скорость отдачи в kB, если 0 то не используется;
Я добавил еще отдачу с помощью Apache, но должна быть включена директива XSendFile On
$client_d->apache = false;//True включает отдачу средствами Apache(работает он с докачкой или нет я пока так и не понял)
//Выполнение команды
$CargaDes->setOnStart(new Exe($client_d));
echo $CargaDes->Start();
Сразу после выполнения метода браузер выдаст окно для сохранения файла
2. Загрузка файла/ов на сервер через браузер с индикатором прогресса
$url_server = "http://ваш_сайт.com/upload.php";//Путь к принимающему скрипту на сервере.
$multiple = 0;//True множественная загрузка файлов, False загрузка по одному файлу
$CargaDes = new CargaDes;
$client_u = new ClientU($url_server, $multiple);
//Не обязательные параметры
$client_u->param = 0;//Добавление данных в форму массивом в переменную param - сервер получит param=>array(ваш массив)
$client_u->ajaxParam = '';//Добавление данных в форму - data.append("key", "val");
$client_u->returns = '';//Добавление действий после выполнения ajax
$client_u->err_file_zero;//Текст ошибки о пустом файле
$client_u->allowed_ext = 'gif,jpg,png,jpe,jpeg,zip,rar,exe,doc,pdf,swf,flv,avi,mp4,mp3';//Разрешенные расширения файлов
$client_u->err_file_ext;//Текст ошибки об отсутствии расширения в списке
$client_u->max_file_size = 0;//Ограничение на размер загружаемых файлов в байтах, по умолчанию отключено
$client_u->err_file_size;//Текст ошибки о превышении установленного размера файла
$client_u->max_file_count = 0;//Ограничение на количество загружаемых файлов, по умолчанию отключено
$client_u->btn_input;//Имя кнопки выбора файлов
$client_u->btn_enviar;//Имя кнопки отправки файлов
$client_u->btn_del;//Имя кнопки удаления файлов из очереди
$client_u->color;//Цвет линии прогресса загрузки
$client_u->css;//Путь к файлу стилей
$server->lang = 'ru';
//Получаем код скрипта
$CargaDes->setOnStart(new Exe($client_u, 'p' ));
echo $CargaDes->Start();
После выполнения метода появится кнопка для выбора файлов и кнопка для загрузки файлов. Индикатор будет появляться для каждого выбранного файла в отдельности.
3. Скачивание файлов с удаленного сервера на свой сервер
$CargaDes = new CargaDes;
$server = new Server();
//Код индикатора
$CargaDes->setOnStart(new Exe($server, 'p'));
echo $CargaDes->Start();
$server->remoteUrl = 'http://сайт.com/test/file.zip';
$server->realFilePath = dirname( __FILE__ ) . '/file.zip';
//Не обязательные параметры
$server->progress = 1;//Подключение/отключение индикатора
$server->speed = 0;//Ограничение скорости
$server->style;//Подключение стиля
$server->color;//Цвет линии прогресса загрузки
$server->erroff = false;//Отключение вывода ошибок
$server->debug = false;//Отладка
$server->login = 0;//Логин отправляемый на сервер, если есть авторизация типа .htaccess
$server->pass = 0;//Пароль отправляемый на сервер, если есть авторизация типа .htaccess
$server->lang = 'ru';
//Выполнение команды
$CargaDes->setOnStart(new Exe($server, 's'));
$r = $CargaDes->Start();
//Вывод ошибок
if( $r['test'] == false ) {echo $r['result'];}
4. Отдаем файл на удаленный сервер со своего сервера
$CargaDes = new CargaDes;
$server = new Server();
//Код индикатора
$CargaDes->setOnStart(new Exe($server, 'p'));
echo $CargaDes->Start();
$server->remoteUrl = 'http://сайт.com/test/priem.php';
$server->realFilePath = dirname( __FILE__ ) . file.zip;//Можно использовать массив файлов
//Не обязательные параметры
$server->post = array( 'login' => 'test', 'pass' => '12345' );//Любые значения которые вы хотите передать на сервер
$server->progress = 1;//Подключение/отключение индикатора
$server->speed = 0;//Ограничение скорости
$server->style;//Подключение стиля
$server->color;//Цвет линии прогресса загрузки
$server->erroff = false;//Отключение вывода ошибок
$server->debug = false;//Отладка
$server->login = 0;//Логин отправляемый на сервер, если есть авторизация типа .htaccess
$server->pass = 0;//Пароль отправляемый на сервер, если есть авторизация типа .htaccess
$server->lang = 'ru';
//Выполнение команды
$CargaDes->setOnStart(new Exe($server, 'u'));
$r = $CargaDes->Start();
//Вывод ошибок
if( $r['test'] == false ) {echo $r['result'];}
По итогу хочу сказать
Если этот класс поможет хотя бы одному человеку я буду очень рад этому. Как я уже говорил в начале буду рад конструктивной критике и дополнениям которые могут привести к улучшению класса. Ссылка на CargaDes.class.
Изменил в статье способы использования класса. И добавил описание того что изменилось в классе.
Вот закончил работу над ошибками, если это можно так назвать.
Что было сделано:
- Привел код к одному стилю с помощью PHPSTORM и старался соблюдать PSR;
- Убрал подчеркивания из названий функций;
- Полностью исключил jQuery;
- Убрал все статические методы;
- Сделал класс как пакет composer;
- cUrl портянку вынес в отдельный метод;
- Постарался соблюсти SRP;
- Сделал исключения и немного изменил вывод ошибок;
- Исправил тело конструкторов;
- Постарался улучшить конструкции if-else;
- Вынес js и html за пределы класса;
- Убрал закрывающий тег ?>;
- Добавил возможность перевода сообщений;
- Добавил папку с исполняющимися примерами.
Что было не сделано:
- Перевод комментариев на английский(если это все одно никому не надо, то зачем тратить время);
- Не сменил названия функций на более понятные(мне не ясно какие, если английские, то смотреть пункт N1);
- Автотесты смотрел, но это оч. сложно сделать универсально т.к. у каждого свои сценарии действий, хотя может я ошибаюсь, то если вы считаете это нужным в классе который никому не нужен у вас есть возможность мне в этом помочь;
- Возможно еще что-то, но я уже не знаю что и у вас есть такая возможность мне об этом сказать.
В целом я постарался исправить, то о чем говорили в комментариях, если будут найдены еще какие либо недочеты или ошибки — пишите постараюсь исправить.
Благодарю за конструктивную критику webdevium и alutskevich, если бы мог, то плюсанул бы вам обязательно.
Так же благодарю всех остальных т.к. у меня появилось понимание моей главной ошибки и родилось пару идей.