'actix-web: limit upload file size

I successfully uploaded the file referring to this example, but I don't know how to limit the size of the file, for example I can't save the file more than 5M

[dependencies]
actix-web = "4"
actix-multipart = "0.4" 

I tried this, but it didn't work.

        web::resource("/upload_file")
            .app_data(web::PayloadConfig::new(1024 * 5))
            .route(web::post().to(views::save_file)),


Solution 1:[1]

middleware

It is used in all requests by default, and can be used in a specified route using req.path()

use actix_web::Error;
use std::future::{ready, Ready};

use actix_web::dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform};
use futures_util::future::LocalBoxFuture;


pub struct ContentLengthLimit {
    pub limit: u64, // byte
}
impl<S, B> Transform<S, ServiceRequest> for ContentLengthLimit
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = ContentLengthLimitMiddleware<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(ContentLengthLimitMiddleware {
            service,
            limit: self.limit,
        }))
    }
}

impl Default for ContentLengthLimit {
    fn default() -> Self {
        Self {
            limit: 1024 * 1024 * 5, /* 5M */
        }
    }
}

pub struct ContentLengthLimitMiddleware<S> {
    service: S,
    limit: u64,
}

impl<S, B> ContentLengthLimitMiddleware<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    fn is_big(&self, req: &ServiceRequest) -> Result<bool, ()> {
        Ok(req
            .headers()
            .get("content-length")
            .ok_or(())?
            .to_str()
            .map_err(|_| ())?
            .parse::<u64>()
            .map_err(|_| ())?
            > self.limit)
    }
}

impl<S, B> Service<ServiceRequest> for ContentLengthLimitMiddleware<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

    forward_ready!(service);

    fn call(&self, req: ServiceRequest) -> Self::Future {
        if let Ok(r) = self.is_big(&req) {
            if r {
                return Box::pin(async { Err(hje("error").actix()) });
            }
        }

        let fut = self.service.call(req);

        Box::pin(async move {
            let res = fut.await?;
            Ok(res)
        })
    }
}

use

App::new().wrap(ContentLengthLimit::default())

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 januw a