Поступила задача: сделать так, чтобы в NetCat 4.72 в поле типа "файл" научиться записывать картинку не только со своего компьютера, но и с URL. Чтобы выработать архитектурно правильный подход, пришлось немного копнуть исходники и разобраться с тем, как же работает механизм хранения файлов в Netcat. Хотя эксперименты я проводил на NetCat 4.72, предполагаю, что и в пятой версии все работает примерно также. Пост публикую из гуманистических соображений, а также чтобы самому не забыть результаты. Да, и чтобы не слишком разочаровывать, ответ на вопрос в заголовке: в полном смысле никак.
Как устроен штатный механизм загрузки хранения файлов в NetCat? А вот как:
Шаг 0: \netcat\message.php
При редактировании объекта, форма изменения объекта в целом обрабатывается файлом message.php Там много всякого кода, но собственно обработка полей происходит в двух других файлах, вызываемых из этого.
Шаг 1: \netcat\message_fields.php
Этот файл подключается примерно в районе 476 строчки message.php и в нем обрабатываются значения форм для режимов добавления/изменения.
Обработка input'ов с файлами начинается кодом case NC_FIELDTYPE_FILE:
и далее NetCat делает примерно следующее (точность не гарантирую, писал по интуиции):
- запоминает старое значение на случай ошибки;
- проверяет, что мы выбрали именно файл для закачки с компьютера, а не что-то другое;
- проверяет, что если выбрано что-то непонятное, то может быть уже существует такой файл и такое поле?
- проверяет, что файл передан, и передан именно через POST;
- узнает параметры поля (тип файловой системы, закачиваемый ли файл);
- сверяет размер файла с допустимыми настройками;
- сверяет тип файла с допустимыми настройками.
Шаг 2: \netcat\message_put.php
Этот файл подключается примерно в районе 646 строчки message.php и он отвечает за отправку значений полей в Базу Данных.
Обработка input'ов с файлами начинается кодом if ($fldType[$i] == NC_FIELDTYPE_FILE)
и далее NetCat делает примерно следующее:
- еще разок проверяет, что файл передан, и передан именно через POST;
- вырезает спецсимволы из имени файла;
- определяет имя, тип, размер, расширение файла;
- готовит запись о файле вот в таком виде:
$fldValue[$i] = $filename.":".$filetype.":".$filesize;
; - проверяет права пользователя;
- генерит путь к файлу:
- в зависимости от типа файловой системы
- делая транслитерацию при необходимости
- добавляя автоматом к имени число, если такой файл уже существует
- удаляет старый файл, если он есть;
- создает необходимые директории;
- наконец, помещает файл туда, куда нужно.
Вот так это работает. Чтобы внедриться сюда, нужно... я не имею ни малейшего понятия, что именно, поскольку файл, переданный методом POST обрабатывается на низком уровне веб-сервером (то есть автоматически, и на эту автоматику опирается NetCat). Как заставить сервер что-то скачать с другого сервера и посчитать, что это что-то передано через POST? Думаю, никак.
Поэтому чтобы внедриться придется полностью разобраться с этим кодом и целиком переписать его, что крайне, крайне трудозатратно, сложно, рискованно и неразумно, поскольку NetCat же живет своей жизнью, а эти изменения касаются ядра системы.
Поэтому думаем дальше.
Придется сделать стороннее решение, ограничив задачу.
Посмотрим, как NetCat хранит данные о картинке в поле image в MySQL: netcat.txt:text/plain:2588:1/32/netcat.txt
При обработке этой информации при рендеринге страницы, она превращается в:
$f_image ссылка на файл $f_image_type MIME-тип файла $f_image_size размер файла Кстати (только при Защищенной Файловой Системе, не мой случай): $f_image_url прямая ссылка на файл $f_image_name оригинальное имя файла $f_image_download количество запросов на скачивание
Очевидно, мы можем заполнить эти данные и сами, если в момент сохранения объекта уже будем знать полный путь к файлу и он там уже будет лежать.
Нет проблем загрузить файл ajax-ом с другого сервера, но что делать, если мы хотим сохранить оба инструмента (и загрузку с компьютера)?
- либо в режиме редактирования на jQuery регулировать дефолтное поле (то есть отключать его, если выбрана загрузка с URL)
- но это приведет к проблемам с удалением и, кстати, а как удалять-то загруженные файлы?
- либо вообще забить на весь дефолтный механизм работы с файлами, и добавить наряду с возможностью закачки картинки с URL также и возможность налету загружать с компьютера через html5
- что даст такие приятные плюшки, как мультизагрузка фото + выбор "ведущей" заявочной фотографии, которая и будет в итоге попадать в поле NetCat
Очевидно, второй вариант предпочтительней.
Картинки будем хранить в директории, жестко привязанной к ID-шнику текущего объекта (кстати, дефолтную адресацию вида netcat_files/sub/cc/ можно было бы изменить (если бы мы не отказались от всего механизма), определив в Условиях Добавления элемент массива: $f_image['folder'] = 'ИмяДиректории';)
Предложенное решение решит поставленную задач, однако полностью обходит механизм работы NetCat, поэтому обладают рядом ограничений:
- картинки заливают только благонадежные администраторы, вся система проверки безопасности NetCat неактивна, проверка ограничений на тип и размер файлов тоже;
- картинки будут храниться в заранее известной директории;
- картинки никак не будут преобразовываться | для этого у нас есть Кэшатор?, и да, я подумал об этом еще когда мы разрабатывали его :)
- все это работает только в режиме изменения объекта, режим добавления купируется | вообще, я склоняюсь к тому, что это поведение стоило бы сделать дефолтным для всех случаев сложных нестандартных функционалов режимов редактирования объекта.
Есть комментарии? Может быть я что-то упустил? Комментируйте!
Все гениальное - просто! Отличное решение для администраторов, о котором я, действительно, не знал. :) ОС семейства Windows при такой операции скачивают файл на компьютер во временную директорию и после этого отдают через POST как ни в чем не бывало:
Таким образом, сложным путем имеет смысла идти только в случае разработки дополнительного функционала, связанного с изображениям.
Finar.
Оставить комментарий