【发布时间】:2021-05-16 01:12:12
【问题描述】:
我尝试了example of actix-multipart 与actix-web v3.3.2 和actix-multipart v0.3.0。
举个简单的例子,
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
}
这很好用,但我想异步处理表单数据。所以我尝试了:
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?
【问题讨论】:
-
您的第一个代码已经是异步的。 OTOH,您的第二个代码在完成读取传入数据之前发送
OK响应,这可能会提示发件人停止发送,假设他们尚未完成。 -
对不起,我的意思是“返回一个响应,然后处理表单数据”。啊,明白了。所以我应该先获取数据,等待,然后返回响应,最后处理数据,对吧?
标签: asynchronous rust actix-web