首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从actix-web中的多部分读取数据

从actix-web中的多部分读取数据
EN

Stack Overflow用户
提问于 2021-02-12 09:25:13
回答 1查看 789关注 0票数 0

我尝试了actix-多部分示例actix-web v3.3.2actix-multipart v0.3.0

举个最小的例子,

代码语言:javascript
复制
use actix_multipart::Multipart;
use actix_web::{post, web, App, HttpResponse, HttpServer};
use futures::{StreamExt, TryStreamExt};

#[post("/")]
async fn save_file(mut payload: Multipart) -> HttpResponse {
    while let Ok(Some(mut field)) = payload.try_next().await {
        let content_type = field.content_disposition().unwrap();
        let filename = content_type.get_filename().unwrap();
        println!("filename = {}", filename);

        while let Some(chunk) = field.next().await {
            let data = chunk.unwrap();
            println!("Read a chunk.");
        }
        println!("Done");
    }
    HttpResponse::Ok().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(save_file))
        .bind("0.0.0.0:8080")?
        .run()
        .await
}

这很好,但是我想异步地处理表单数据。所以我试了一下:

代码语言:javascript
复制
use actix_multipart::Multipart;
use actix_web::{post, web, App, HttpResponse, HttpServer};
use futures::{StreamExt, TryStreamExt};

#[post("/")]
async fn save_file(mut payload: Multipart) -> HttpResponse {
    actix_web::rt::spawn(async move {
        while let Ok(Some(mut field)) = payload.try_next().await {
            let content_type = field.content_disposition().unwrap();
            let filename = content_type.get_filename().unwrap();
            println!("filename = {}", filename);

            while let Some(chunk) = field.next().await {
                let data = chunk.unwrap();
                println!("Read a chunk.");
            }
            println!("Done");
        }
    });
    HttpResponse::Ok().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(save_file))
        .bind("0.0.0.0:8080")?
        .run()
        .await
}

(将actix_web::rt::spawn添加到save_file.)

但这是行不通的-- "Done"从未打印过的信息。第二种情况下显示的"Read a chunk"数量少于第一种情况,因此我猜在读取所有数据之前,field.next().await不可能因为某种原因而终止。

我对异步编程不太了解,所以我不知道为什么field.next()没有在actix_web::rt::spawn中工作。

我的问题是:为什么是这样,我如何处理actix_web::rt::spawn

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-13 02:50:04

当你打这个电话时:

代码语言:javascript
复制
actix_web::rt::spawn(async move {
    // do things...
});

spawn返回用于轮询任务的JoinHandle。当您删除该句柄(通过不将其绑定到任何东西)时,任务将被“分离”,也就是说,它在后台运行。

actix文档在这里并不特别有用,但是actix在幕后使用tokio运行时。一个关键的问题是,在tokio中,生成的任务不能保证完成。执行者需要知道,不知何故,它应该为这个未来工作。在第二个示例中,生成的任务从未被.await编辑过,也没有通过通道与任何其他任务进行通信。

最有可能的是,生成的任务永远不会被轮询,也不会取得任何进展。为了确保它完成,您可以使用.await JoinHandle (它将驱动任务完成)或.await其他一些依赖于生成任务中的工作的Future (通常通过使用一个通道)。

至于您更普遍的目标,工作已经异步执行了!最有可能的是,actix正在执行您在第二个示例中试图做的工作:在接收到请求时,它会产生一个任务来处理请求,并反复轮询它(以及其他活动请求),直到它完成,然后发送一个响应。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66169240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档