DevGang
Авторизоваться

Построение устройства для изменения размера изображения с помощью Flask, React и Vite

Привет!

В этом уроке я покажу вам, как создать простой ресайзер изображений с помощью Flask, React и Vite.

Требования

  • Базовые знания Python/React
  • Установленный OpenCV

Создание серверной части

Сначала мы создадим серверную часть с помощью Flask, которая будет обрабатывать загрузку изображений, преобразовывать их и затем предоставлять преобразованное изображение в ответе. Для этого мы будем использовать OpenCV и NumPy.

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

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

Следуя лучшим практикам, мы будем кодировать сервер, используя виртуальную среду Python. Это легко сделать в Python 3 с помощью следующей команды:

python3 -m venv env

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

source env/bin/activate

Теперь вы должны находиться в виртуальной среде Python.

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

Flask
flask_cors
opencv-python
numpy

Для установки библиотек просто выполните следующую команду:

pip install -r requirements.txt

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

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

from flask import Flask, request, send_file
from flask_cors import CORS
import cv2
import numpy as np

После этого нам нужно инициализировать приложение Flask и отключить CORS, это позволит приложению React получить доступ к серверу без каких-либо проблем.

app = Flask(__name__)
CORS(app)

Далее следует маршрут, который будет использоваться для обработки загрузки файлов.

Он выглядит следующим образом:

@app.route('/upload', methods=['POST'])
def upload():
    if 'image' not in request.files:
        return 'No file uploaded', 400

    file = request.files['image']

    if not file.content_type.startswith('image/'):
        return 'File is not an image', 400

    if file.filename == '':
        return 'no selected file', 400

    if file:
        npimg = np.fromfile(file, np.uint8)
        img = cv2.imdecode(npimg, cv2.IMREAD_UNCHANGED)

        width = int(request.form.get('width', 1024))
        height = int(request.form.get('height', 1024))

        resized_image = cv2.resize(img, (width, height))

        convert_status, buffer = cv2.imencode('.jpg', resized_image)

        if not convert_status:
            return 'Failed to convert image', 500

        temp_file = 'temp_image.jpg'
        cv2.imwrite(temp_file, resized_image)

        return send_file(temp_file, as_attachment=True)

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

Если файл существует и является изображением, он будет изменен в размере и преобразован в jpg-изображение, в случае успешного завершения процесса файл возвращается клиенту.

В заключение нам нужна только функция main:

if __name__ == '__main__':
    app.run(debug=True)

Всё, что было сделано выше, - это запуск приложения.

Далее мы создадим приложение React для работы с фронтендом.

Создание клиентской части

Наконец, нам нужен пользовательский интерфейс для загрузки и преобразования изображения. Для фронт-энда будет использоваться React, который будет создан с помощью Vite. Чтобы создать новый проект Vite, просто выполните следующую команду:

yarn create vite

Следуйте подсказкам, чтобы создать новое приложение React, использующее Javascript. Мы также будем использовать Bootstrap для пользовательского интерфейса и axios для обработки запросов. Эти пакеты можно установить с помощью следующих команд:

yarn add axios
yarn add bootstrap

Чтобы применить стили Bootstrap, добавьте следующую строку в файл src/main.jsx:

import 'bootstrap/dist/css/bootstrap.min.css';

После этого мы создадим новый компонент React для формы загрузки изображения, создадим новую директорию components в директории src и создадим новый файл ImageUploadForm.jsx, после создания заполним его следующим образом:

import { useState } from 'react';
import axios from 'axios';

const ImageUploadForm = () => {
    const [height, setHeight] = useState('1024');
    const [width, setWidth] = useState('1024');
    const [file, setFile] = useState(null);
    const [image, setImage] = useState(null);

    const handleSubmit = async (e) => {
        e.preventDefault();

        const formData = new FormData();
        formData.append('height', height);
        formData.append('width', width);
        formData.append('image', file);

        try {
            const response = await axios.post('http://localhost:5000/upload', formData, {
                headers: { 'Content-Type': 'multipart/form-data' },
                responseType: 'blob'
            });

            const objectURL = URL.createObjectURL(response.data);
            setImage(objectURL);
        } catch (error) {
            console.error('error uploading file', error);
        }
    };

    return (
        <>
            <form onSubmit={handleSubmit} className="container mt-4">
                <div className="mb-3">
                    <label htmlFor="height" className="form-label">Height:</label>
                    <input type="number" className="form-control" id="height" value={height} onChange={(e) => setHeight(e.target.value)}/>
                </div>
                <div className="mb-3">
                    <label htmlFor="width" className="form-label">Width:</label>
                    <input type="number" className="form-control" id="width" value={width} onChange={(e) => setWidth(e.target.value)} />
                </div>
                <div className="mb-3">
                    <label htmlFor="image" className="form-label">Image:</label>
                    <input type="file" className="form-control" id="image" onChange={(e) => setFile(e.target.files[0])} />
                </div>

                <button type="submit" className="btn btn-primary">Submit</button>
            </form>

            {image && <img src={image} />}
        </>
    );
}

export default ImageUploadForm;

Вышеописанное отображает форму, содержащую три элемента: один для высоты изображения, один для ширины изображения и один для самого файла изображения.

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

Готово, теперь мы можем запустить и сервер, и приложение!

Запуск приложения

Чтобы запустить сервер Flask, просто выполните следующую команду в виртуальной среде Python:

python main.py

Чтобы запустить приложение React, просто выполните следующую команду:

yarn dev

Вышеуказанная команда должна автоматически открыть ваш браузер и перенаправить вас в приложение React.

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

Заключение

Здесь я показал, как обрабатывать загрузку изображений с помощью Flask и преобразовывать их с помощью OpenCV. Мы также использовали React и Vite для создания фронтенда и простой формы, позволяющей пользователю выбрать и преобразовать изображение.

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

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

Надеюсь, вы узнали что-то новое из этой статьи, так как я получил массу удовольствия от ее создания, и мне нужно было что-то подобное для личного использования.

Спасибо за прочтение!

Источник:

#JavaScript #React #Начинающим
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу