单文件和多文件html的区别就是multiple
toml
[dependencies]
rocket = "0.5.1"
[package.metadata.rocket]
config = "Rocket.toml"
Rocket.toml 配置文件上传的大小限制
# Rocket.toml
[default.limits]
form = "160MB" # 设置文件上传的最大大小为16MB
data-form = "160MB"
file = "160MB"
[development.limits]
form = "160MB" # 设置文件上传的最大大小为16MB
data-form = "160MB"
file = "160MB"
[production.limits]
form = "160MB" # 设置文件上传的最大大小为16MB
data-form = "160MB"
file = "160MB"
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<h1>Upload a File</h1>
<!-- 表单的 action 指向你的 Rocket 应用的 '/upload' 路由 -->
<!-- 表单的 enctype 设置为 "multipart/form-data" 以支持文件上传 -->
<form action="http://127.0.0.1:8000/upload" method="post" enctype="multipart/form-data">
<!-- 文件输入字段 -->
<!-- 单文件不需要multiple -->
<input type="file" name="file" id="file" multiple><br><br>
<!-- 提交按钮 -->
<input type="submit" value="Upload File">
</form>
</body>
</html>
单文件rs
use rocket::{routes,
post,
fs::TempFile,
form::FromForm,
form::Form,
http::Status,
};
use std::path::{Path};
#[derive(FromForm)]
struct Upload<'f> {
file: TempFile<'f>,
}
#[post("/", format = "multipart/form-data", data = "<form>")]
async fn upload_file(mut form: Form<Upload<'_>>) -> Result<String, Status> {
// 直接从 Option<FileName> 中提取文件名并转换为 String,但是这种是没有后缀的,被优化过的
// let file_name = match form.file.name() {
// Some(s) => s,
// None => "None-0" //可以用uuid
// };
// // 从 Path 中提取文件名,包括后缀名
// let file_path = form.file.path().ok_or(Status::InternalServerError)?;
// let path = Path::new(file_path); // 将路径转换为 Path 类型
// let file_name1 = path.file_name().ok_or(Status::InternalServerError)?.to_str().ok_or(Status::InternalServerError)?.to_string();
// println!("File name with extension: {}", file_name1); // 打印完整的临时文件名
//取出上传的时候的老的文件名
let file_name = form.file.raw_name().map(|name| name.dangerous_unsafe_unsanitized_raw().as_str())
.unwrap_or_else(|| "default_filename.pdf"); // 如果没有文件名,则使用默认值
println!("{}", file_name);
//获取是json jpg png zip 。。。。。
//let extension = form.file.content_type().map(|s| s.media_type().sub().to_string());
//println!("{:?}", extension);
//打印tmp_path目录
let tmp_path = Path::to_str(form.file.path().unwrap()).map(|s| s.to_string()).unwrap();
println!("{}", tmp_path);
// 确保上传目录存在
let upload_dir = "uploads"; // 你可以根据需要修改这个路径
std::fs::create_dir_all(upload_dir).map_err(|_| Status::InternalServerError)?;
// 尝试将文件保存到服务器
let upload_path = std::path::Path::new(upload_dir).join(file_name); // 使用 join 方法将目录和文件名组合成 Path
if form.file.copy_to(upload_path.clone()).await.is_ok() {
// 文件上传成功后的逻辑
//删除临时目录的文件
std::fs::remove_file(tmp_path).map_err(|_| Status::InternalServerError)?;
Ok(format!("上传成功 {}", upload_path.display()))
} else {
Err(Status::InternalServerError)
}
}
#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
rocket::build()
.mount("/upload", routes![upload_file])
.launch()
.await?;
Ok(())
}
多文件
use rocket::{routes,
post,
fs::TempFile,
form::FromForm,
form::Form,
http::Status,
};
use std::path::{Path};
#[derive(FromForm)]
struct Upload<'f> {
file: Vec<TempFile<'f>>,
}
#[post("/", format = "multipart/form-data", data = "<form>")]
async fn upload_file(mut form: Form<Upload<'_>>) -> Result<String, Status> {
let upload_dir = "uploads";
std::fs::create_dir_all(upload_dir).map_err(|_| Status::InternalServerError)?;
// 遍历 form.files 并使用 iter_mut 获取每个文件的可变引用
for temp_file in form.file.iter_mut() {
// 取出上传时的原始文件名
let file_name = temp_file.raw_name()
.map(|name| name.dangerous_unsafe_unsanitized_raw().as_str())
.unwrap_or_else(|| "default_filename.pdf"); // 如果没有文件名,则使用默认值
println!("{}", file_name);
let upload_path = Path::new(upload_dir).join(file_name.to_string());
let tmp_path = Path::to_str(temp_file.path().unwrap()).map(|s| s.to_string()).unwrap();
println!("{}", tmp_path);
// 尝试将文件保存到服务器
if !temp_file.copy_to(upload_path.clone()).await.is_ok() {
std::fs::remove_file(tmp_path).map_err(|_| Status::InternalServerError)?;
return Err(Status::InternalServerError);
}
}
Ok(format!("上传成功"))
}
#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
rocket::build()
.mount("/upload", routes![upload_file])
.launch()
.await?;
Ok(())
}
纯文本上传
#[post("/upload2", format = "text/plain", data = "<file>")]
async fn upload(mut file: TempFile<'_>) -> std::io::Result<()> {
let permanent_location = PathBuf::from("F:\\code\\rocket-upload\\uploads\\11.txt");
file.copy_to(permanent_location).await
}
postman模拟纯文本上传,写入文件
在Body部分,选择raw选项,然后在右侧的下拉菜单中选择plain类型或者text类型。