Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

После перезапуска программы сбрасываются настройки #394

Open
BlagoYar opened this issue Jan 30, 2025 · 31 comments
Labels

Comments

@BlagoYar
Copy link

Пруф
https://youtu.be/IEn_McQi0BM

@zenden2k
Copy link
Owner

zenden2k commented Jan 31, 2025

Баг воспроизводится. Скоро исправлю.

Когда добавляется аккаунт к ftp серверу, создаются пустые настройки сервера для этого аккаунта. Т.е. настройки сервера привязаны к аккаунту. Это ожидаемое поведение. Сейчас это приводит к пропаданию сервера полностью.

@zenden2k zenden2k added the bug label Jan 31, 2025
@BlagoYar
Copy link
Author

Баг воспроизводится. Скоро исправлю.

Когда добавляется аккаунт к ftp серверу, создаются пустые настройки сервера для этого аккаунта. Т.е. настройки сервера привязаны к аккаунту. Это ожидаемое поведение. Сейчас это приводит к пропаданию сервера полностью.

Ещё одна проблема - когда делаю скриншот и сохраняю на диск, то постоянно одно и тоже имя ScreenShot-001 и нумерация не увеличивается.

@zenden2k
Copy link
Owner

Вы имеете в виду после перезапуска программы? Или в запущенной программе счетчик не увеличивается?

Как вы делаете скриншот?

@BlagoYar
Copy link
Author

Вы имеете в виду после перезапуска программы? Или в запущенной программе счетчик не увеличивается?

Как вы делаете скриншот?

https://youtu.be/uPPfjG-Ynxk

zenden2k added a commit that referenced this issue Feb 1, 2025
@BlagoYar
Copy link
Author

BlagoYar commented Feb 6, 2025

Я извиняюсь, а вы не в курсе, есть ли максимально похожий функционал в каком-нибудь приложении для андроид? То бишь главное это указать свой FTP сервер и чтобы после выгрузки ссылка копировалась. А если и возможно то с превью картинки.

@zenden2k
Copy link
Owner

zenden2k commented Feb 7, 2025

Не знаю

zenden2k added a commit that referenced this issue Feb 7, 2025
@BlagoYar
Copy link
Author

BlagoYar commented Feb 8, 2025

Можете дать все расширения, которые программа распознаёт, как изображения?

ПС. Хочу сделать редирект на nginx для них и сейчас вот svg закачал, а оно распознаётся программой, как файл, а не изображение.

@zenden2k
Copy link
Owner

zenden2k commented Feb 8, 2025

"jpg", "jpeg", "jpe", "jif", "jfif", "png", "bmp", "gif","tif", "tiff", "webp", "heic", "heif", "avif"

@BlagoYar
Copy link
Author

"jpg", "jpeg", "jpe", "jif", "jfif", "png", "bmp", "gif","tif", "tiff", "webp", "heic", "heif", "avif"

Спасибо, а можете ещё сказать в каком файле код для наложения миниатюры?
Хочу для андроид приложения точно так же сделать (flat-ом) под php, но что-то не получается?

@zenden2k
Copy link
Owner

zenden2k commented Feb 11, 2025

https://github.com/zenden2k/image-uploader/blob/master/Source/Core/Images/ImageConverterPrivate_gdiplus.cpp#L308

@BlagoYar
Copy link
Author

BlagoYar commented Feb 11, 2025

https://github.com/zenden2k/image-uploader/blob/master/Source/Core/Images/ImageConverterPrivate_gdiplus.cpp#L308

Можете ещё подсказать, как добиться прозрачности фона. Уже второй день мучаю. Уже пробовал готовой шаблон (просто прозрачный png 275x145 при миниатюре 180x180), никак что-то не хочет.
Знаю давно, что это проблемная тема. Как вы её решили?

Если что вот код обработки

$overlayTopThickness = 1; // Толщина подложки сверху, слева и справа
$overlayBottomHeight = 30; // Высота подложки внизу

// Создаем новое изображение с прозрачным фоном
$background = new Imagick();
$background->newImage($thumbWidth + 2 * $overlayTopThickness, $thumbHeight + $overlayBottomHeight, new ImagickPixel("none"), 'png');
$background->setImageFormat('png');
$background->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);

// Композитим миниатюру поверх прозрачного фона
$image = new Imagick($imagePath);
$image->setImageFormat('png');
$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);
$image->thumbnailImage($thumbWidth, $thumbHeight, true);
$background->compositeImage($image, Imagick::COMPOSITE_OVER, $overlayTopThickness, $overlayTopThickness);

// Создаем цветные подложки
$overlayTop = new Imagick();
$overlayTop->newImage($thumbWidth + 2 * $overlayTopThickness, $overlayTopThickness, new ImagickPixel("#F7F7F7"), 'png');
$overlayTop->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);
$overlaySide = new Imagick();
$overlaySide->newImage($overlayTopThickness, $thumbHeight + $overlayBottomHeight, new ImagickPixel("#F7F7F7"), 'png');
$overlaySide->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);
$overlayBottom = new Imagick();
$overlayBottom->newImage($thumbWidth + 2 * $overlayTopThickness, $overlayBottomHeight, new ImagickPixel("#F7F7F7"), 'png');
$overlayBottom->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);

// Композитим подложки поверх прозрачного фона
$background->compositeImage($overlayTop, Imagick::COMPOSITE_OVER, 0, 0); // Подложка сверху
$background->compositeImage($overlaySide, Imagick::COMPOSITE_OVER, 0, $overlayTopThickness); // Подложка слева
$background->compositeImage($overlaySide, Imagick::COMPOSITE_OVER, $thumbWidth + $overlayTopThickness, $overlayTopThickness); // Подложка справа
$background->compositeImage($overlayBottom, Imagick::COMPOSITE_OVER, 0, $thumbHeight); // Подложка снизу

// Путь к изображению-иконке
$lupaImagePath = '/var/www/html/domain.com/scripts/lupa.png';

// Загружаем изображение-иконку
$lupa = new Imagick($lupaImagePath);
$lupaWidth = $lupa->getImageWidth();
$lupaHeight = $lupa->getImageHeight();

// Композитим иконку на подложку в правый нижний угол
$lupaX = $thumbWidth + $overlayTopThickness - $lupaWidth - 5; // 5 пикселей отступ
$lupaY = $thumbHeight + $overlayBottomHeight - $lupaHeight - 8; // 5 пикселей отступ

$background->compositeImage($lupa, Imagick::COMPOSITE_OVER, $lupaX, $lupaY);


// Добавляем текст
$draw = new ImagickDraw();
$draw->setFillColor('#222222'); // Цвет текста
$draw->setFont('/usr/share/fonts/truetype/tahoma/tahoma.ttf'); // Надежный шрифт
$draw->setFontSize(12);
$draw->setGravity(Imagick::GRAVITY_NORTHWEST);

// Получаем высоту изображения и рассчитываем координаты
$imageHeight = $background->getImageHeight();
$yCoordinate = $imageHeight - $overlayBottomHeight + 8; // Опускаем текст вниз

// Текст с отступами
if ($fileSizeKB >= 1024) {
    $fileSizeMB = number_format($fileSizeKB / 1024, 2, '.', ''); // Точное деление, 2 знака после точки
    $text = "{$thumbWidth}x{$thumbHeight} [{$fileSizeMB} Mb]";
} else {
    $text = "{$thumbWidth}x{$thumbHeight} [{$fileSizeKB} Kb]";
}

// Координаты текста с учетом толщины подложки
$background->annotateImage($draw, $overlayTopThickness + 5, $yCoordinate, 0, $text);

if (!empty($this->thumbCreatingParams['DrawFrame'])) {
    $background->borderImage(new ImagickPixel('black'), 5, 5);
}

// Сохранение для отладки
$background->writeImage('/tmp/test_output.png'); // Проверь вручную

return $background;

@zenden2k
Copy link
Owner

zenden2k commented Feb 12, 2025

Всё портит эта строчка

$background->borderImage(new ImagickPixel('black'), 5, 5);

Вам лучше использовать класс ImagickDraw:

$image = new Imagick($imagePath);
$image->setImageFormat('png');
$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);
$image->thumbnailImage($thumbWidth, $thumbHeight, true);

$draw = new ImagickDraw();
// Композитим миниатюру поверх прозрачного фона
$draw->composite(Imagick::COMPOSITE_OVER, $overlayTopThickness, $overlayTopThickness, $image->getImageWidth(),  $image->getImageHeight(), $image);

$draw->setStrokeColor(new ImagickPixel('black'));
$draw->setFillColor(new ImagickPixel('none'));
$draw->setStrokeWidth(1);
$draw->setStrokeOpacity(1);
$draw->rectangle(0, 0, $thumbWidth + 2 * $overlayTopThickness-1, $thumbHeight + $overlayBottomHeight + $overlayTopThickness-1);


//.......

// Сохранение для отладки

$imagick = new \Imagick();
$imagick->newImage($thumbWidth + 2 * $overlayTopThickness, $thumbHeight + $overlayBottomHeight + $overlayTopThickness, new ImagickPixel('none'));
$imagick->setImageFormat("png");
$imagick->drawImage($draw);
$imagick->writeImage('./test_output.png'); 

@zenden2k
Copy link
Owner

zenden2k commented Feb 12, 2025

Знаю давно, что это проблемная тема. Как вы её решили?

Я использую совсем другую библиотеку (GdiPlus). У меня не было таких проблем.

В общем, мне кажется лучше всё рисовать на ImageDraw

@BlagoYar
Copy link
Author

В общем, мне кажется лучше всё рисовать на ImageDraw

Да, спасибо. Помогло.

ПС. Есть возможность реализовать в программе указать собственный обработчик?
Например по принципу этого приложения

@zenden2k
Copy link
Owner

ПС. Есть возможность реализовать в программе указать собственный обработчик?

Какой обработчик?

@BlagoYar
Copy link
Author

ПС. Есть возможность реализовать в программе указать собственный обработчик?

Какой обработчик?

Ну в моём случае это php скрипт (но может быть на любом языке). Ссылка на него указывается в приложении, добавляются если нужно заголовки, response и т.д.

@zenden2k
Copy link
Owner

@BlagoYar
Copy link
Author

BlagoYar commented Feb 17, 2025

Я так и не понял. Вам либо нужно это https://zenden2k.github.io/image-uploader/ru_RU/advanced.html#servers

либо это https://zenden2k.github.io/image-uploader/api/html/uploadfilter_8h.html#UploadFilters

Ну да, оно, только вот создал xml файл, пример

<Server>
    <URL>https://your-domain/path-to-scripts/upload_bbcodeB.php</URL>
    <FileFormName>files[]</FileFormName>
    <AdditionalFormData>
        <Field>
            <Name>Authorization</Name>
            <Value>Bearer VALID_TOKEN_BBCODEb</Value>
        </Field>
    </AdditionalFormData>
</Server>




Поместил в Data\Servers\Upload.xml, запустил программу, но в списке его нет.

@zenden2k
Copy link
Owner

zenden2k commented Feb 17, 2025

Это неправильный формат
Должно быть что-то вроде этого:

<Servers>
    <Server Name="server name">
            <Actions>
                <Action Type="upload" Url="https://your-domain/path-to-scripts/upload_bbcodeB.php" PostParams="files[]=%filename%;Authorization=Bearer VALID_TOKEN_BBCODEb" 
                    RegExp='https://your-domain/files/(\d*)' AssignVars="File:0"/>
            </Actions>
            <Result ImageUrlTemplate="https://your-domain/files/$(File)"/>
    </Server>
</Servers>

хотя обычно Authorization передается в заголовках запроса:

<Servers>
    <Server Name="server name">
            <Actions>
                <Action Type="upload" Url="https://your-domain/path-to-scripts/upload_bbcodeB.php" PostParams="files[]=%filename%;" 
                    CustomHeaders="Authorization:Bearer VALID_TOKEN_BBCODEb" RegExp='https://your-domain/files/(\d*)' AssignVars="File:0"/>
            </Actions>
            <Result ImageUrlTemplate="https://your-domain/files/$(File)"/>
    </Server>
</Servers>

@BlagoYar
Copy link
Author

BlagoYar commented Feb 17, 2025

У меня такой скрипт

<?php
// error_reporting(E_ALL);
// ini_set('display_errors', 1);

    define('UPLOAD_DIR_IMAGES', getenv('UPLOAD_DIR_IMAGES'));
    define('UPLOAD_DIR_FILES', getenv('UPLOAD_DIR_FILES'));
    define('VALID_TOKEN', getenv('VALID_TOKEN_BBCODEb'));

    class FileUploader {
        private $validToken;
        private $imageConverter;

        public function __construct($token, $imageConverter) {
            $this->validToken = $token;
            $this->imageConverter = $imageConverter;
        }

        public function authorize() {
            $headers = apache_request_headers();
            $authHeader = isset($headers['Authorization']) ? $headers['Authorization'] : '';
            if ($authHeader !== 'Bearer ' . $this->validToken) {
                $this->unauthorizedResponse();
            }
        }

        private function unauthorizedResponse() {
            header('HTTP/1.1 401 Unauthorized');
            readfile("/usr/share/nginx/html/401.html");
            exit;
        }

        public function uploadFile($file) {
            try {
                $file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
                $uploadDir = in_array($file_extension, $this->getImageExtensions()) ? UPLOAD_DIR_IMAGES : UPLOAD_DIR_FILES;
                $uploadFile = $uploadDir . basename($file['name']);

                // Логирование директории и имени файла
                error_log("Попытка загрузить файл в директорию: $uploadDir");
                error_log("Имя файла: " . basename($file['name']));

                // Проверяем права на директорию
                if (!is_writable($uploadDir)) {
                    error_log("Ошибка: Директория $uploadDir недоступна для записи.");
                    return "error: Директория недоступна для записи.";
                }

                while (file_exists($uploadFile)) {
                    $path_info = pathinfo($uploadFile);
                    $uploadFile = $path_info['dirname'] . '/' . $path_info['filename'] . '_' . $this->generateRandomString() . '.' . $path_info['extension'];
                }

                if (move_uploaded_file($file['tmp_name'], $uploadFile)) {
                    error_log("Файл успешно загружен: $uploadFile");

                    if (in_array($file_extension, $this->getImageExtensions())) {
                        $randomString = $this->generateRandomString(16);
                        $thumbnailFile = $uploadDir . 'thumb_' . $randomString . '.png';

                        if ($file_extension === 'svg') {
                            $thumbnail = $this->imageConverter->createSvgThumbnail($uploadFile, filesize($uploadFile));
                        } else {
                            $thumbnail = $this->imageConverter->createThumbnail($uploadFile, filesize($uploadFile), $file_extension);
                        }

                        $thumbnail->writeImage($thumbnailFile);
                        error_log("Миниатюра успешно создана: $thumbnailFile");

                        $uploadFileURI = rawurlencode(basename($uploadFile));
                        $thumbnailFileURI = rawurlencode(basename($thumbnailFile));

                        return '[url=https://domain.com/' . $uploadFileURI . '][img]https://domain.com/' . $thumbnailFileURI . '[/img][/url]';
                    } else {
                        $uploadFileURI = rawurlencode(basename($uploadFile));
                        return 'https://domain.com/' . $uploadFileURI;
                    }
                } else {
                    throw new Exception("Ошибка при перемещении файла.");
                }
            } catch (Exception $e) {
                error_log("Ошибка: " . $e->getMessage());
                return "error: Произошла ошибка при обработке файла.";
            }
        }

        private function generateRandomString($length = 4) {
            $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            $charactersLength = strlen($characters);
            $randomString = '';
            for ($i = 0; $i < $length; $i++) {
                $randomString .= $characters[rand(0, $charactersLength - 1)];
            }
            return $randomString;
        }

        private function getImageExtensions() {
            return ['jpg', 'jpeg', 'jpe', 'jif', 'jfif', 'png', 'bmp', 'gif', 'tiff', 'tif', 'webp', 'heic', 'heif', 'avif', 'svg', 'ico'];
        }
    }

    class ImageConverterPrivate {
        private $thumbCreatingParams;

        public function __construct($thumbCreatingParams) {
            $this->thumbCreatingParams = $thumbCreatingParams;
        }

    public function createThumbnail($imagePath, $fileSize, $fileExtension) {
        $image = new Imagick($imagePath);

        if ($image->getNumberImages() > 1 && strtolower($fileExtension) === 'ico') {
            $maxWidth = 0;
            $maxHeight = 0;
            $imageIndex = 0;
            foreach ($image as $index => $frame) {
                $frameWidth = $frame->getImageWidth();
                $frameHeight = $frame->getImageHeight();
                if ($frameWidth > $maxWidth || $frameHeight > $maxHeight) {
                    $maxWidth = $frameWidth;
                    $maxHeight = $frameHeight;
                    $imageIndex = $index;
                }
            }
            $image->setIteratorIndex($imageIndex);
        }

        $newWidth = $image->getImageWidth();
        $newHeight = $image->getImageHeight();
        $thumbWidth = $this->thumbCreatingParams['Width'];

        if ($this->thumbCreatingParams['ResizeMode'] === 'trByWidth') {
            $thumbHeight = (int) round(($thumbWidth / $newWidth) * $newHeight);
        } elseif ($this->thumbCreatingParams['ResizeMode'] === 'trByHeight') {
            $thumbHeight = $newHeight;
            $thumbWidth = $newWidth;
        }

        $overlayBottomHeight = 30;
        $frameThickness = 3;
        $padding = 5;
        $transparencyPadding = 5;

        $thumbCopy = clone $image;
        $thumbCopy->thumbnailImage($thumbWidth, $thumbHeight, true);
        $thumbCopy->roundCorners(3, 3);

        $backgroundWidth = $thumbWidth + 6 + 2 * $transparencyPadding;
        $backgroundHeight = max($thumbHeight + $overlayBottomHeight + 6 + 2 * $transparencyPadding, $thumbHeight + 33 + 2 * $transparencyPadding);

        $background = new Imagick();
        $background->newImage($backgroundWidth, $backgroundHeight, new ImagickPixel('none'));
        $background->setImageFormat('png');

        $frame = new Imagick();
        $frame->newImage($backgroundWidth - 2 * $transparencyPadding, $backgroundHeight - 2 * $transparencyPadding, new ImagickPixel('none'));
        $frame->setImageFormat('png');

        $colorLayer = new Imagick();
        $colorLayer->newImage($frame->getImageWidth(), $frame->getImageHeight(), new ImagickPixel('#222222'));
        $colorLayer->setImageFormat('png');

        $frameMask = new Imagick();
        $frameMask->newImage($frame->getImageWidth(), $frame->getImageHeight(), new ImagickPixel('white'));
        $frameMask->setImageFormat('png');
        $frameMask->roundCorners(3, 3);

        $colorLayer->compositeImage($frameMask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
        $frame->compositeImage($colorLayer, Imagick::COMPOSITE_OVER, 0, 0);
        $background->compositeImage($frame, Imagick::COMPOSITE_OVER, $transparencyPadding, $transparencyPadding);

        $thumbX = 3 + $transparencyPadding;
        $thumbY = 3 + $transparencyPadding;

        $background->compositeImage($thumbCopy, Imagick::COMPOSITE_OVER, $thumbX, $thumbY);

        $draw = new ImagickDraw();
        $draw->setFillColor('#FFFFFF');
        $draw->setFont('/usr/share/fonts/truetype/tahoma/tahoma.ttf');
        $draw->setFontSize(12);
        $draw->setGravity(Imagick::GRAVITY_NORTHWEST);

        $textX = 10 + $transparencyPadding;
        $textY = 0;
        $textY += $backgroundHeight - $overlayBottomHeight + 5 - $transparencyPadding;
        $fileSizeKB = round($fileSize / 1024, 1);

        if ($fileSizeKB >= 1024) {
            $fileSizeMB = number_format($fileSizeKB / 1024, 2, '.', '');
            $text = "{$newWidth}x{$newHeight} [{$fileSizeMB} Mb]";
        } else {
            $text = "{$newWidth}x{$newHeight} [{$fileSizeKB} Kb]";
        }

        $background->annotateImage($draw, $textX, $textY, 0, $text);

        $lensImagePath = '/var/www/html/domain.com/scripts/lens-white.png';
        $lens = new Imagick($lensImagePath);
        $lensX = $background->getImageWidth() - $lens->getImageWidth() - 12 - $transparencyPadding;
        $lensY = $background->getImageHeight() - $lens->getImageHeight() - 12 - $transparencyPadding;
        $background->compositeImage($lens, Imagick::COMPOSITE_OVER, $lensX, $lensY);

        // $thumbCopy->writeImage('/tmp/thumb_with_mask.png');
        // $background->writeImage('/tmp/final_output.png');

        return $background;
    }

         public function createSvgThumbnail($imagePath, $fileSize) {
        $image = new Imagick($imagePath);

        if ($image->getNumberImages() > 1 && strtolower($fileExtension) === 'ico') {
            $maxWidth = 0;
            $maxHeight = 0;
            $imageIndex = 0;
            foreach ($image as $index => $frame) {
                $frameWidth = $frame->getImageWidth();
                $frameHeight = $frame->getImageHeight();
                if ($frameWidth > $maxWidth || $frameHeight > $maxHeight) {
                    $maxWidth = $frameWidth;
                    $maxHeight = $frameHeight;
                    $imageIndex = $index;
                }
            }
            $image->setIteratorIndex($imageIndex);
        }

        $newWidth = $image->getImageWidth();
        $newHeight = $image->getImageHeight();
        $thumbWidth = $this->thumbCreatingParams['Width'];

        if ($this->thumbCreatingParams['ResizeMode'] === 'trByWidth') {
            $thumbHeight = (int) round(($thumbWidth / $newWidth) * $newHeight);
        } elseif ($this->thumbCreatingParams['ResizeMode'] === 'trByHeight') {
            $thumbHeight = $newHeight;
            $thumbWidth = $newWidth;
        }

        $overlayBottomHeight = 30;
        $frameThickness = 3;
        $padding = 5;
        $transparencyPadding = 5;

        $thumbCopy = clone $image;
        $thumbCopy->thumbnailImage($thumbWidth, $thumbHeight, true);
        $thumbCopy->roundCorners(3, 3);

        $backgroundWidth = $thumbWidth + 6 + 2 * $transparencyPadding;
        $backgroundHeight = max($thumbHeight + $overlayBottomHeight + 6 + 2 * $transparencyPadding, $thumbHeight + 33 + 2 * $transparencyPadding);

        $background = new Imagick();
        $background->newImage($backgroundWidth, $backgroundHeight, new ImagickPixel('none'));
        $background->setImageFormat('png');

        $frame = new Imagick();
        $frame->newImage($backgroundWidth - 2 * $transparencyPadding, $backgroundHeight - 2 * $transparencyPadding, new ImagickPixel('none'));
        $frame->setImageFormat('png');

        $colorLayer = new Imagick();
        $colorLayer->newImage($frame->getImageWidth(), $frame->getImageHeight(), new ImagickPixel('#222222'));
        $colorLayer->setImageFormat('png');

        $frameMask = new Imagick();
        $frameMask->newImage($frame->getImageWidth(), $frame->getImageHeight(), new ImagickPixel('white'));
        $frameMask->setImageFormat('png');
        $frameMask->roundCorners(3, 3);

        $colorLayer->compositeImage($frameMask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
        $frame->compositeImage($colorLayer, Imagick::COMPOSITE_OVER, 0, 0);
        $background->compositeImage($frame, Imagick::COMPOSITE_OVER, $transparencyPadding, $transparencyPadding);

        $thumbX = 3 + $transparencyPadding;
        $thumbY = 3 + $transparencyPadding;

        $background->compositeImage($thumbCopy, Imagick::COMPOSITE_OVER, $thumbX, $thumbY);

        $draw = new ImagickDraw();
        $draw->setFillColor('#FFFFFF');
        $draw->setFont('/usr/share/fonts/truetype/tahoma/tahoma.ttf');
        $draw->setFontSize(12);
        $draw->setGravity(Imagick::GRAVITY_NORTHWEST);

        $textX = 10 + $transparencyPadding;
        $textY = 0;
        $textY += $backgroundHeight - $overlayBottomHeight + 5 - $transparencyPadding;
        $fileSizeKB = round($fileSize / 1024, 1);

        if ($fileSizeKB >= 1024) {
            $fileSizeMB = number_format($fileSizeKB / 1024, 2, '.', '');
            $text = "{$newWidth}x{$newHeight} [{$fileSizeMB} Mb]";
        } else {
            $text = "{$newWidth}x{$newHeight} [{$fileSizeKB} Kb]";
        }

        $background->annotateImage($draw, $textX, $textY, 0, $text);

        $lensImagePath = '/var/www/html/domain.com/scripts/lens-white.png';
        $lens = new Imagick($lensImagePath);
        $lensX = $background->getImageWidth() - $lens->getImageWidth() - 12 - $transparencyPadding;
        $lensY = $background->getImageHeight() - $lens->getImageHeight() - 12 - $transparencyPadding;
        $background->compositeImage($lens, Imagick::COMPOSITE_OVER, $lensX, $lensY);

        // $thumbCopy->writeImage('/tmp/thumb_with_mask.png');
        // $background->writeImage('/tmp/final_output.png');

        return $background;
        }
    }

    $thumbCreatingParams = [
        'Width' => 180,
        'Height' => 180,
        'ResizeMode' => 'trByWidth',
        'DrawFrame' => true
    ];

    $imageConverter = new ImageConverterPrivate($thumbCreatingParams);
    $fileUploader = new FileUploader(VALID_TOKEN, $imageConverter);
    $fileUploader->authorize();

    // file_put_contents("upload_log.txt", print_r($_FILES, true), FILE_APPEND);
    // file_put_contents("upload_debug_log.txt", json_encode($_FILES, JSON_PRETTY_PRINT), FILE_APPEND);

    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['files'])) {
        $responses = [];
        foreach ($_FILES['files']['tmp_name'] as $index => $tmpName) {
            $file = [
                'name' => $_FILES['files']['name'][$index],
                'type' => $_FILES['files']['type'][$index],
                'tmp_name' => $tmpName,
                'error' => $_FILES['files']['error'][$index],
                'size' => $_FILES['files']['size'][$index]
            ];
            $responses[] = $fileUploader->uploadFile($file);
        }
        echo implode("\n", $responses);
    } else {
        echo "error: Неверный метод запроса или отсутствует файл.";
    }
?>

xml такой должен быть?

<Servers>
    <Server Name="Upload BBCode B">
        <Actions>
            <Action
                Type="post"
                Url="https://domain.com/scripts/upload_bbcodeB.php"
                PostParams="files[]=%filename%;"
                CustomHeaders="Authorization: Bearer MyToken"
                RegExp="https://domain.com/(\w+\.\w+)"
                AssignVars="File:0"
            />
        </Actions>
        <Result ImageUrlTemplate="https://domain.com/$(File)"/>
    </Server>
</Servers>

Скрипт обрабатывает изображения и я получаю готовые ссылки в bbcode

return '[url=https://domain.com/' . $uploadFileURI . '][img]https://domain.com/' . $thumbnailFileURI . '[/img][/url]';

Наверное нужно, чтобы возвращалось просто ссылка на файл, а ImageUloader уже сам подставит миниатюру если я выберу соответствующую обработку, потому что сейчас ошибка "cannot obtain the necessary information from server response"

@zenden2k
Copy link
Owner

zenden2k commented Feb 17, 2025

Если вы возвращаете BBCode, тогда можно использовать такое регулярное выражение

<Action
                Type="post"
                Url="https://domain.com/scripts/upload_bbcodeB.php"
                PostParams="files[]=%filename%;"
                CustomHeaders="Authorization:Bearer MyToken"
                RegExp="\[url=(.*?)\]\[img\](.*?)\[" AssignVars="Image:0;Thumb:1;" 
            />
<Result ImageUrlTemplate="$(Image)" ThumbUrlTemplate="$(Thumb)" />

@BlagoYar
Copy link
Author

BlagoYar commented Feb 17, 2025

Если вы возвращаете BBCode, тогда можно использовать такое регулярное выражение


Всё равно эту ошибку получаю "cannot obtain the necessary information from server response".
Но в принципе, если программа уже умеет сама оформлять в bbcode, тогда просто url-ом лучше отвечать.

@zenden2k
Copy link
Owner

Включите отладку

<Server Name="Upload BBCode B" Debug="1">

и посмотрите, что выдаст.

@BlagoYar
Copy link
Author

Включите отладку

и посмотрите, что выдаст.

Image

Image

Image
И ещё получаю ответ от своего скрипта
"error: Неверный метод запроса или отсутствует файл."

Хотя сам скрипт работает, вот из curl

admin@proxi ~ # curl -X POST "https://domain.com/scripts/upload_bbcodeB.php" -H "Authorization: Bearer TOKEN" -F "files[]=@/home/admin/AdGuard.svg"
[url=https://domain.com/AdGuard.svg][img]https://domain.com/thumb_c9CiYSXajyf2mjrF.png[/img][/url]

@zenden2k
Copy link
Owner

Ой, я ошибся, должно быть Action Type=upload

<Action
               Type="upload"
               Url="https://domain.com/scripts/upload_bbcodeB.php"
               PostParams="files[]=%filename%;"
               CustomHeaders="Authorization:Bearer MyToken"
               RegExp="\[url=(.*?)\]\[img\](.*?)\[" AssignVars="Image:0;Thumb:1;" 
           />

@BlagoYar
Copy link
Author

Ой, я ошибся, должно быть Action Type=upload

Да, так работает. У меня это скрипт обрабатывает и файлы и изображения. Что нужно прописать, чтобы и выборе серверов для файлов он тоже был? И как иконку указать для сервера?

@zenden2k
Copy link
Owner

zenden2k commented Feb 17, 2025

Что нужно прописать, чтобы и выборе серверов для файлов он тоже был?

<Server Name="Upload BBCode B" Types="image file" >

И как иконку указать для сервера?

Сохранить иконку в папку Data\Favicons\ в файл с именем сервера в нижнем регистре в формате .ico :
"upload bbcode b.ico"

@BlagoYar
Copy link
Author

Что нужно прописать, чтобы и выборе серверов для файлов он тоже был?

> И как иконку указать для сервера?

Сохранить иконку в папку Data\Favicons\ в файл с именем сервера в нижнем регистре в формате .ico : "upload bbcode b.ico"

При закачке файлов та ошибка, что была "cannot obtain the necessary information from server response". Наверное потому что скрипт для файлов отдаёт только чистый url. А можно в xml типа условия сделать, мол если файл, то вот такой-то result, если изображения то такой-то?

@zenden2k
Copy link
Owner

zenden2k commented Feb 17, 2025

Можно в php-скрипте возвращать массив:

return [ 
    'direct_url' => $uploadFileURI,
    'thumb_url' => $thumbnailFileURI
];

а в конце конвертировать его в JSON:

header('Content-Type: application/json');
echo json_encode($responses, JSON_PRETTY_PRINT);

А в xml использовать функцию JSON:

<Servers>
    <Server Name="Upload BBCode B" Types="image file">
        <Actions>
            <Action
                Type="upload"
                Url="https://domain.com/scripts/upload_bbcodeB.php"
                PostParams="files[]=%filename%;"
                CustomHeaders="Authorization:Bearer MyToken"
            >
                <Call Function="json" Arg1=".[0].direct_url" AssignVars="DirectUrl:0;"/>
                <Call Function="json" Arg1=".[0].thumb_url" AssignVars="ThumbUrl:0;"/>
            </Action>
        </Actions>
        <Result ImageUrlTemplate="$(DirectUrl)" ThumbUrlTemplate="$(ThumbUrl)" />
    </Server>
</Servers>

@zenden2k
Copy link
Owner

А можно в xml типа условия сделать, мол если файл, то вот такой-то result, если изображения то такой-то?

В xml условия можно добавить, только если написать хитроумное регулярное выражение.

@BlagoYar
Copy link
Author

Можно в php-скрипте возвращать массив:

return [
'direct_url' => $uploadFileURI,
'thumb_url' => $thumbnailFileURI
];
а в конце конвертировать его в JSON:

header('Content-Type: application/json');
echo json_encode($responses, JSON_PRETTY_PRINT);
А в xml использовать функцию JSON:

Спасибо!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants