Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File upload 使用actix web Framework在Rust中的web服务器上上载文件时,使用原始文件名保存文件_File Upload_Rust_Rust Actix_Actix Web - Fatal编程技术网

File upload 使用actix web Framework在Rust中的web服务器上上载文件时,使用原始文件名保存文件

File upload 使用actix web Framework在Rust中的web服务器上上载文件时,使用原始文件名保存文件,file-upload,rust,rust-actix,actix-web,File Upload,Rust,Rust Actix,Actix Web,我正在使用actix web框架在Rust中创建一个web服务器。目前我正在使用actix multipart进行文件上传和im 在官方Actix文档中有一个例子: use std::cell::Cell; use std::fs; use std::io::Write; use actix_multipart::{Field, Multipart, MultipartError}; use actix_web::{error, middleware, web, App, Error, Htt

我正在使用actix web框架在Rust中创建一个web服务器。目前我正在使用actix multipart进行文件上传和im

在官方Actix文档中有一个例子:

use std::cell::Cell;
use std::fs;
use std::io::Write;

use actix_multipart::{Field, Multipart, MultipartError};
use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer};
use futures::future::{err, Either};
use futures::{Future, Stream};

pub fn save_file(field: Field) -> impl Future<Item = i64, Error = Error> {
    let file_path_string = "upload.png";
    let file = match fs::File::create(file_path_string) {
        Ok(file) => file,
        Err(e) => return Either::A(err(error::ErrorInternalServerError(e))),
    };
    Either::B(
        field
            .fold((file, 0i64), move |(mut file, mut acc), bytes| {
                // fs operations are blocking, we have to execute writes
                // on threadpool
                web::block(move || {
                    file.write_all(bytes.as_ref()).map_err(|e| {
                        println!("file.write_all failed: {:?}", e);
                        MultipartError::Payload(error::PayloadError::Io(e))
                    })?;
                    acc += bytes.len() as i64;
                    Ok((file, acc))
                })
                .map_err(|e: error::BlockingError<MultipartError>| {
                    match e {
                        error::BlockingError::Error(e) => e,
                        error::BlockingError::Canceled => MultipartError::Incomplete,
                    }
                })
            })
            .map(|(_, acc)| acc)
            .map_err(|e| {
                println!("save_file failed, {:?}", e);
                error::ErrorInternalServerError(e)
            }),
    )
}

pub fn upload(
    multipart: Multipart,
    counter: web::Data<Cell<usize>>,
) -> impl Future<Item = HttpResponse, Error = Error> {
    counter.set(counter.get() + 1);
    println!("{:?}", counter.get());

    multipart
        .map_err(error::ErrorInternalServerError)
        .map(|field| save_file(field).into_stream())
        .flatten()
        .collect()
        .map(|sizes| HttpResponse::Ok().json(sizes))
        .map_err(|e| {
            println!("failed: {}", e);
            e
        })
}

fn index() -> HttpResponse {
    let html = r#"<html>
        <head><title>Upload Test</title></head>
        <body>
            <form target="/" method="post" enctype="multipart/form-data">
                <input type="file" name="file"/>
                <input type="submit" value="Submit"></button>
            </form>
        </body>
    </html>"#;

    HttpResponse::Ok().body(html)
}

fn main() -> std::io::Result<()> {

    HttpServer::new(|| {
        App::new()
            .data(Cell::new(0usize))
            .wrap(middleware::Logger::default())
            .service(
                web::resource("/")
                    .route(web::get().to(index))
                    .route(web::post().to_async(upload)),
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
}
使用std::cell::cell;
使用std::fs;
使用std::io::Write;
使用actix_multipart::{Field,multipart,MultipartError};
使用actix_web::{error,middleware,web,App,error,HttpResponse,HttpServer};
使用futures::future::{err,或者};
使用未来:{Future,Stream};
pub fn save_文件(字段:field)->impl Future{
让file\u path\u string=“upload.png”;
让file=match fs::file::create(文件路径字符串){
确定(文件)=>文件,
Err(e)=>返回一个::A(Err(error::ErrorInternalServerError(e)),
};
要么::B(
领域
.fold((文件,0i64),move |(mut文件,mut acc),bytes |{
//fs操作被阻塞,我们必须执行写操作
//关于线程池
web::块(移动| |{
file.write_all(bytes.as_ref()).map_err(| e |{
println!(“file.write_all failed:{:?}”,e);
多端口错误::有效负载(错误::有效负载错误::Io(e))
})?;
acc+=bytes.len()作为i64;
Ok((文件,acc))
})
.map|u err(| e:error::BlockingError |{
匹配e{
错误::阻塞错误::错误(e)=>e,
错误::BlockingError::Cancelled=>MultipartError::不完整,
}
})
})
.地图(|(|,acc)| acc)
.map|u err(| e|{
println!(“保存_文件失败,{:?}”,e);
错误::ErrorInternalServerError(e)
}),
)
}
发布fn上传(
多部分:多部分,
计数器:web::Data,
)->impl未来{
counter.set(counter.get()+1);
println!(“{:?}”,counter.get());
多部分
.map_err(error::ErrorInternalServerError)
.map(| field |保存_文件(field).into_stream())
.flatte()
.collect()
.map(| size | HttpResponse::Ok().json(size))
.map|u err(| e|{
println!(“失败:{}”,e);
E
})
}
fn index()->HttpResponse{
让html=r#”
上传测试
"#;
HttpResponse::Ok().body(html)
}
fn main()->std::io::Result{
HttpServer::新建(|||){
App::new()
.data(单元格::新建(0usize))
.wrap(中间件::记录器::默认值())
.服务(
web::资源(“/”)
.route(web::get().to(索引))
.route(web::post().到_async(上载)),
)
})
.bind(“127.0.0.1:8080”)?
.run()
}
这将是一个最小的工作实现,到目前为止效果良好。但正如您所看到的,filepathstring是一个自定义字符串,它将服务器上的文件重命名为upload.png(
let file\u path\u string=“upload.png”

那么,有没有一种简单的方法可以检索原始文件名,并将其用作服务器上上载文件的文件名?

NK建议的content\u disposition()方法可能就是您在这里想要的。因此,您可以替换:

let file_path_string = "upload.png";
比如:

let file_path_string = match field.content_disposition().unwrap().get_filename() {
    Some(filename) => filename.replace(' ', "_").to_string(),
    None => return Either::A(err(error::ErrorInternalServerError("Couldn't read the filename.")))
}

请注意,这不是一个好主意。这可能导致严重的安全问题。请参阅,字段类型提供了content_disposition()方法。到目前为止效果很好-这是否意味着您已经解决了前面的问题()?我找到了解决方法,但并没有像我在前面的问题中提到的那样使用AppState结构。因此,变通办法不是一个理想的解决方案,我的问题还没有解决。