Rust中实现用户上传功能的开源项目


此 Rust 项目演示了一个简单的 PasteBin 应用程序的实现,其中使用 Actix 实现 Web 服务器功能,使用 Rusqlite 进行数据库操作,并使用 HTML 进行用户界面。

它允许用户提交文本内容,将其存储在本地数据库中,并使用生成的 URL 检索它。

提供的 HTML 文件定义了用户界面的结构和设计,而 Rust 代码则处理 HTTP 请求、数据库交互和 URL 路由。

什么是PasteBin,为什么是Rust?

  • PasteBin是一个简单的在线服务,允许用户上传和共享文本或代码片段。它是开发人员快速共享代码或配置文件的方便工具。
  • Rust以其安全性和性能而闻名,是Web服务的绝佳选择。它提供了内存安全性,而无需垃圾收集器,使其适用于高性能Web应用程序。


运行应用程序:

  • 要运行该应用程序,请cargo run在终端中执行。
  • 通过导航至 来访问 Web 浏览器中的应用程序http://localhost:8080。
  • 在文本区域中输入所需的内容,然后单击“提交”按钮以生成用于粘贴的 URL。
  • 与其他人共享生成的 URL 以访问粘贴内容。

依赖
请确保您的机器上安装了Rust和Cargo。您还需要将以下依赖项添加到您的Cargo.toml文件:

  • actix-web用于我们的Web服务器和路由。
  • rusqlite用于SQLite数据库交互。
  • rand用于为每个粘贴生成唯一的令牌。
  • actix-files用于提供静态文件。
  • serde用于序列化和重新序列化数据。

[dependencies]
actix-web = "3.0"
rusqlite = { version =
"0.29.0", features = ["bundled"] }
rand =
"0.8"
actix-files =
"0.5"
serde = { version =
"1.0", features = ["derive"] }

在 main.rs 中:

  • main.rs 主函数初始化我们的 SQLite 数据库,并使用 Actix-web 设置网络服务器。它将路由映射到处理程序,并启动服务器,在 localhost:8080 上监听请求。
  • 当用户提交粘贴时,会使用 rand crate 生成一个唯一的标记。该标记作为粘贴的标识符,与粘贴内容一起存储在我们的 SQLite 数据库中。
  • 检索粘贴内容非常简单:我们在数据库中查询与 URL 中提供的标记相关联的内容。如果找到,我们就会显示;否则,我们就会显示 "未找到粘贴 "消息。

详细描述
1、导入:
代码从 Actix、Rusqlite 和其他库导入必要的模块和特征,以处理 HTTP 请求、数据库操作并生成随机令牌。

2、数据结构:
定义一个FormData结构体来表示从客户端接收到的表单数据,以及一个AppState结构体来保存数据库连接。

FormDataStruct:让我们定义一个结构体来表示从客户端接收的表单数据。它将包括一个单独的字段content来存储提交的内容。

#[derive(serde::Deserialize)]
struct FormData {
    content: String,
}

AppState :该结构用于保存应用程序状态,在本例中,是一个与 SQLite 数据库的连接,该连接以 Mutex 封装,用于跨线程安全访问。

struct AppState {
    db: Mutex<Connection>,
}

3、main函数:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let db = Connection::open("pastes.db").expect("Failed to open database");

    db.execute(
       
"CREATE TABLE IF NOT EXISTS pastes (token TEXT PRIMARY KEY, content TEXT)",
        params![],
    )
    .expect(
"Failed to create table");

    let app_state = web::Data::new(AppState {
        db: Mutex::new(db),
    });

    HttpServer::new(move || {
        App::new()
            .app_data(app_state.clone())
            .service(web::resource(
"/style.css").to(|| {
                async { NamedFile::open(
"src/style.css") }
            }))
            .route(
"/", web::get().to(index))
            .route(
"/submit", web::post().to(submit))
            .route(
"/paste/{token}", web::get().to(get_paste))
    })
    .bind(
"127.0.0.1:8080")? // Binding the server to the specified address
    .run()
    .await
// Starting the server and awaiting its completion
}

这是程序的入口点。它执行以下任务:
  • 打开或创建名为“pastes.db”的SQLite数据库文件。
  • 如果“pastes”表不存在,则创建该表,其中包含标记(主键)和内容列。
  • 使用数据库连接定义应用程序状态。
  • 配置Actix Web服务器路由,包括提供静态文件(“/style.css”)、处理索引请求(“/”)、提交表单数据(“/submit”)和检索粘贴内容(“/paste/{token}”)。
  • 将服务器绑定到地址“127.0.0.1:8080”并启动服务器。

4、路由处理程序:

  • index:处理对根URL(“/”)的GET请求并返回索引页的HTML内容。为我们的 index.html 文件提供服务,为用户提供一个提交粘贴内容的简单表单。
  • submit:处理对“/submit”的POST请求,并使用随机生成的令牌将提交的内容插入数据库。为每个粘贴生成一个唯一的标记,将其存储在数据库中,并将用户重定向到其粘贴的 URL。
  • get_paste:处理对“/paste/{token}”的 GET 请求,并从数据库中检索与提供的令牌关联的内容。

async fn index() -> impl Responder { // sends the response body for index.html
    HttpResponse::Ok().body(include_str!(
"index.html"))
}

async fn submit(content: web::Form<FormData>, data: web::Data<AppState>) -> impl Responder {
// it takes some content
    .
    .
    .
    .
}

async fn get_paste(token: web::Path<String>, data: web::Data<AppState>) -> impl Responder {
// this function helps to retrieve the value someone is sending to us
    .
    .
    .
    .
}

5、数据库操作:
打开或创建名为“pastes.db”的 SQLite 数据库文件。
如果不存在,则创建一个名为“pastes”的表,其中包含标记(主键)和内容列。


6、Actix Web 服务器配置:
配置 Actix Web 服务器路由以提供静态文件(“/style.css”)和处理 HTTP 请求(“/”、“/submit”、“/paste/{token}”)。
将服务器绑定到地址“127.0.0.1:8080”并启动服务器。