Skip to content
This repository has been archived by the owner on Jan 21, 2024. It is now read-only.

Upload files larger than 256kb #2

Closed
Nohac opened this issue Aug 22, 2022 · 6 comments
Closed

Upload files larger than 256kb #2

Nohac opened this issue Aug 22, 2022 · 6 comments

Comments

@Nohac
Copy link

Nohac commented Aug 22, 2022

When I use this library and I try to upload a file larger than the default 256kb file limit, I get the following error:

Multipart error: Payload reached size limit.

This is the code I use for the endpoint:

#[derive(FromMultipart, ToSchema)]
struct Payload {
    other: String,
    #[schema(value_type = String, format = Binary)]
    payload: File,
}

#[utoipa::path(
    request_body(content = Payload, content_type = "multipart/form-data"),
    responses(
        (status = 201, description = "Payload successfully uploaded"),
    )
)]
#[post("/payload/upload")]
async fn task_upload(metadata: MultipartForm<Payload>) -> impl Responder {
    println!("{}, {:?}", metadata.other, metadata.payload.filename);

    HttpResponse::Ok()
}

To fix this, I've tried to change the default size for both actix and this library:

HttpServer::new(move || {
    App::new()
        .app_data(state.clone())
        .app_data(actix_web::web::PayloadConfig::new(500 * 1024 * 1024))
        .app_data(MultipartFormConfig::default().file_limit(500 * 1024 * 1024))
        .service(
            SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-doc/openapi.json", openapi.clone()),
        )
        .service(task_upload)
})
.bind(("0.0.0.0", 8080))?
.run()
.await

Nothing seems to help. When I use Multipart and stream directly from actix, the file limit error does not kick in.
I'm not sure if the issue happens in this library, or if it is actix as this is unfortunately a part of the framework that lacks documentation.

@jacob-pro
Copy link
Owner

@Nohac Hi, sorry it is not working for you, that is very odd

The default limits for this library you can see here:

https://github.com/jacob-pro/actix-easy-multipart/blob/master/actix-easy-multipart/src/lib.rs#L65

So low that I think this is actually a mistake - by default this library limits to 50KiB total for file uploads (I had meant to set it to 50MiB)!

But what you are doing with MultipartFormConfig::default().file_limit(500 * 1024 * 1024) is correct way to override this / how it is intended to be used.

Please could you try using the lower level API, see the test-case here (where I have set a test limit of 2 bytes) - can you try seeing if this will accept larger files?

https://github.com/jacob-pro/actix-easy-multipart/blob/master/actix-easy-multipart/src/load.rs#L294

@jacob-pro
Copy link
Owner

Also I see what you mean about a "default 256KiB payload limit":
https://docs.rs/actix-web/latest/actix_web/web/struct.PayloadConfig.html
That only applies to certain built in actix web extractors, it isn't used by this library, so you can ignore that one.

I'm going to assume you're actually hitting the 50KiB default of this library

@Nohac
Copy link
Author

Nohac commented Aug 23, 2022

Using the builder seems to work.

#[post("/payload/upload")]
async fn task_upload(payload: actix_multipart::Multipart) -> impl Responder {
    let test = Loader::builder()
        .file_limit(500 * 1024 * 1024)
        .build()
        .load_fields(payload)
        .await
        .unwrap();
    println!("{:?}", test);

    HttpResponse::Ok()
}

The output:

[Text(Text { name: "other", text: "test" }), File(File { file: NamedTempFile("/tmp/.tmpARMEq5"), size: 313196, name: "payload", filename: Some("bigfile.bin"), mime: "application/octet-stream" })]

@jacob-pro
Copy link
Owner

Hi @Nohac thanks for checking that.

I have had a go myself with this config, and wasn't able to replicate your results 😕

[dependencies]
actix-web = "4"
actix-easy-multipart = "2.1.1"
use actix_easy_multipart::extractor::{MultipartForm, MultipartFormConfig};
use actix_easy_multipart::{File, FromMultipart};
use actix_web::{post, App, HttpResponse, HttpServer, Responder};

#[derive(FromMultipart)]
struct Payload {
    payload: File,
}

#[post("/payload/upload")]
async fn task_upload(metadata: MultipartForm<Payload>) -> impl Responder {
    let text = format!("Success: {:?}", metadata.0.payload);
    HttpResponse::Ok().body(text)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || {
        App::new()
            .app_data(MultipartFormConfig::default().file_limit(500 * 1024 * 1024))
            .service(task_upload)
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}
## Attempt with a 480MB file - is accepted
$ stat --printf="%s" pycharm-professional-2022.2.1.exe
493030488

$ curl --form payload='@pycharm-professional-2022.2.1.exe' -X POST http://localhost:8080/payload/upload
Success: File { file: NamedTempFile("C:\\Users\\jacob\\AppData\\Local\\Temp\\.tmp5gpZSS"), size: 493030488, name: "payload", filename: Some("pycharm-professional-2022.2.1.exe"), mime: "application/octet-stream" }


## Attempt with a 720MB file - is denied
$ stat --printf="%s" ideaIU-2022.2.exe
736935368

$ curl --form payload='@ideaIU-2022.2.exe' -X POST http://localhost:8080/payload/upload
Multipart error: Payload reached size limit.

Please can you confirm which versions your are using?

@Nohac
Copy link
Author

Nohac commented Aug 24, 2022

I figured out what the issue was thanks to your code.

Apparently I used the wrong MultipartFormConfig. I used actix_easy_multipart::validated::MultipartFormConfig instead of actix_easy_multipart::extractor::MultipartFormConfig. I should have included the imports I used in my code, that way I wouldn't have to waste so much of your time.

Either way, the issue is solved. Thanks!

@Nohac Nohac closed this as completed Aug 24, 2022
@jacob-pro
Copy link
Owner

Hi @Nohac

Glad it is working for you now - I can see how that is easily confused - in a future version I will try to use better names!

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

No branches or pull requests

2 participants