Показать сообщение отдельно
  #45 (permalink)  
Старый 16.02.2018, 13:38
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от kupidon
Я не знаю как его загрузить
У вас не только с этим проблемы. Мне некогда, поэтому общие положения.

Форма содержит поле для ввода сетевого пути к файлу. Этих полей может быть много. Как клонировать и добавить поле в форму на форуме уже не раз писалось, найти. Пусть это поле имеет имя file[].

Также формой передается id товара, а при необходимости и его родителя.

Загрузка локальных файлов осуществляется полем тоже с именем file[].

Загрузку файлов можно начитать только если id товара действительно, а если и родитель, то и он. Это условие описано ранее. Далее могут быть два сценария:
1) последовательная загрузка: сначала локальные файлы если есть с полной обработкой, затем сетевые при их наличии с полной обработкой
2) комбинированная: создается массив ссылок на временные файлы, затем проходом в цикле они отдаются в полную обработку.

Сервер имеет функцию производящую основные операции с изображениями. Если функция возвращает 0, значит ошибок при обработке не возникало. В противном случае, это код ошибки.

$mime = ['image/png', 'image/jpeg']; //разрешенные типы
$size = 1000000; //макс. размер.

function processingIMG($f) {
    if(!$im = @imagecreatefromstring($f)) return 1; //файл не является изображением
    //далее операции
    //сохранение
    return 0; 
}


В случае первого сценария проверяются файлы массива $_FILES на отсутствие ошибок при загрузке, загружен ли файл по HTTP, предварительно на тип, и на допустимый размер. Проверка на размер очень важна, о ней ниже. Если Эти условия соблюдены временный файл отдается processingIMG(file_get_contents($_FILES['file']['tmp_name'][$i])).

Затем обрабатываются файлы сетевые если они есть, и это тоже массив файлов.

if($url = array_diff(filter_var_array($_POST['file'], FILTER_VALIDATE_URL), [false])) {
    foreach($url as $a) {
        $hdr = get_headers($a, 1);
        if(strpos($hdr[0], '200')) {
            if(in_array($hdr['Content-Type'], $mime) && $hdr['Content-Length'] <= $size) $upl[] = $a;    
        }
    }
    
    foreach($upl as $url) {
        if($f = @file_get_contents($url)) {
            if(processingIMG($f)) echo 'Error';    
        }
    }
}


Из полученного массива ссылок сетевых файлов будут удалены те, что имеют некорректный сетевой путь. Прежде чем реально загружать сетевые файлы, сначала получается информация о них, посредством запроса заголовков. После анализа заголовков из массива списка сетевых файлов будут удалены те, у которых заголовок не вернул статус 200, и у которых тип не является разрешенным и размер больше разрешенного. При этом надо учесть, что изображение может отдаваться не по прямой ссылке, а скриптом, но в заголовке будет не тип изображения, и он будет исключен из набора. Кроме этого url не обязательно прямой путь, возможны перенаправления, количество которых должно быть определено, если разрешено, и проанализировано (рассказывать не буду, запускайте get_headers на примерах, смотрите результаты, анализируйте, думайте, действуйте).

Полученный массив валидных ссылок обходится циклом, где производится загрузка файлов посредством file_get_contents($url) и загруженный файл отдается также на дальнейшую обработку в processingIMG().

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

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

О проверке на размер. Если файл будет обрабатываться графической библиотекой (GD и прочее), то нужно учитывать следующее. Если эта загрузка для себя и вы не враг себе, а также гарантируете, что ваш вход надежно защищен, то терпимо. Но если закинуть на сервер изображение 10000х10000, которое в формате JPEG может быть сжато и до смешного размера, то проверку на размер файла оно пройдет. Но для работы с этим файлов в GD под ресурс потребуется памяти 10000х10000Х32 = 3 200 000 000 байт (GD не будет спрашивать вас нужен ли вам альфа канал, он все равно под него отведет один байт). И у вас будут возникать фатальные ошибки.

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

Последний раз редактировалось laimas, 16.02.2018 в 13:58.
Ответить с цитированием