Возможно ли ограничить размер файла, не получив его полностью?

Вопрос или проблема

Я использую Rust и Actix для загрузки ZIP-файлов, и теперь я хочу проверить, чтобы размер загруженного ZIP-файла был меньше 100 МБ. Вот как выглядит код:

async fn upload_full_proj(
    MultipartForm(form): MultipartForm<FullProjUpload>,
    login_user_info: LoginUserInfo,
) -> HttpResponse {
    return save_full_proj(form, &login_user_info).await;
}

А вот как определяется FullProjUpload:

use actix_multipart::form::{MultipartForm, tempfile::TempFile, text::Text};

#[derive(Debug, MultipartForm)]
pub struct FullProjUpload {
    #[multipart(rename = "file")]
    pub files: Vec<TempFile>,
    pub project_id: Text<String>,
    pub parent: Text<String>
}

Я пытался ограничить размер в точке входа проекта следующим образом:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    rust_i18n::set_locale("zh-CN");
    log4rs::init_file("log4rs.yaml", Default::default()).unwrap();
    let port: u16 = get_app_config("texhub.port").parse().unwrap();
    let address = ("0.0.0.0", port);
    consume_sys_events();
    HttpServer::new(|| {
        App::new().app_data(
            MultipartFormConfig::default()
                .total_limit(1048576) // 1 МБ = 1024 * 1024
                .memory_limit(2097152) // 2 МБ = 2 * 1024 * 1024
                .error_handler(handle_multipart_error),
        )
    })
    .workers(3)
    .bind(address)?
    .run()
    .await
}

И это хорошо работает, но как ограничить размер файла в каждом API Actix? Потому что лимит на загрузку изображений (<2 МБ) отличается от лимита на ZIP-файлы проекта (<100 МБ). Мне также нужно проверить размер, не дожидаясь полной загрузки файла.

Вы можете указать .app_data на уровне каждого Scope/Resource, а не только на уровне всего App.

Просто предоставьте другую конфигурацию через .app_data на Scope/Resource, для которого вы хотите иметь другую конфигурацию. Будет использоваться самая конкретная конфигурация.

Ответ или решение

Вопрос о том, возможно ли ограничить размер файла без полного его получения, имеет особую актуальность в контексте работы с большими файлами в сетевых приложениях. Как вы уже правильно заметили, в Actix-Web существует возможность установить ограничения на размер загружаемых файлов, используя MultipartFormConfig, что позволяет контролировать размер загружаемого контента.

Чтобы решить вашу задачу и установить разные ограничения на размер файлов для различных маршрутов в Actix-Web, вы можете использовать подход с применением app_data на уровне конкретного маршрута (Scope или Resource).

Вот пример того, как вы можете реализовать это в вашем коде:

use actix_web::{web, App, HttpResponse, HttpServer, Result};
use actix_multipart::form::{MultipartForm, tempfile::TempFile, text::Text};
use actix_multipart::{MultipartFormConfig};
use actix_web::middleware;
use std::io;

#[derive(Debug, MultipartForm)]
pub struct ImageUpload {
    #[multipart(rename = "file")]
    pub image: TempFile,
}

#[derive(Debug, MultipartForm)]
pub struct FullProjUpload {
    #[multipart(rename = "file")]
    pub files: Vec<TempFile>,
    pub project_id: Text<String>,
    pub parent: Text<String>,
}

async fn upload_image(form: MultipartForm<ImageUpload>) -> HttpResponse {
    // Логика обработки изображения
    HttpResponse::Ok().body("Image uploaded successfully")
}

async fn upload_full_proj(form: MultipartForm<FullProjUpload>) -> HttpResponse {
    // Логика обработки проекта
    HttpResponse::Ok().body("Project uploaded successfully")
}

#[actix_web::main]
async fn main() -> io::Result<()> {
    let port: u16 = 8080; // Ваш порт

    HttpServer::new(move || {
        App::new()
            .service(web::scope("/upload")
                .app_data(MultipartFormConfig::default()
                    .total_limit(1024 * 1024 * 2) // 2MB для изображений
                    .memory_limit(1024 * 1024 * 2)
                )
                .route("/image", web::post().to(upload_image))
            )
            .service(web::scope("/upload_project")
                .app_data(MultipartFormConfig::default()
                    .total_limit(1024 * 1024 * 100) // 100MB для zip файлов
                    .memory_limit(1024 * 1024 * 10) // Можете настроить по необходимости
                )
                .route("/full_proj", web::post().to(upload_full_proj))
            )
    })
    .bind(("0.0.0.0", port))?
    .run()
    .await
}

В этом примере мы создаем два отдельных маршрута: один для загрузки изображений с ограничением в 2 МБ, а другой для загрузки zip-файлов с ограничением в 100 МБ. Каждому маршруту назначается своя конфигурация MultipartFormConfig, что позволяет нам контролировать максимальный размер файла, который может быть загружен на каждом конкретном эндпоинте.

Кроме того, если вы хотите проверять размер файла в процессе загрузки, вам нужно будет использовать обработку событий, связанные с прогрессом загрузки. Однако, с текущим API Actix, это может потребовать сложной обработки и необходимости самостоятельно реализовать логику чтения потоков данных.

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

Оцените материал
Добавить комментарий

Капча загружается...