impliment file upload backend and frontend with rust

impliment with actix_web

use std::path::PathBuf;
use actix_web::{web, App, HttpResponse, HttpServer};
use futures::StreamExt;

#[allow(warnings)]
async fn upload(mut payload: web::Payload) -> HttpResponse {
    let path = "./stream.data";
    let pathbuf = PathBuf::from(path);
    if pathbuf.exists(){
        std::fs::remove_file(pathbuf.clone()).unwrap();
    }
    while let Some(item) = payload.next().await {
        let chunk = item.unwrap();
        doe::fs::append_data_to_file(path, chunk.to_vec()).unwrap();
    }
    if let Ok(d) = std::fs::read(path){
        if let Some(ex) = get_file_extension(&d){
            std::fs::copy(path, format!("./stream.{}",ex)).unwrap();
        }else{
            std::fs::copy(path, format!("./stream")).unwrap();
        }
    }
    if pathbuf.exists(){
        std::fs::remove_file(pathbuf).unwrap();
    }
    HttpResponse::Ok().finish()
}


#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(web::resource("/").route(web::post().to(upload)))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

impliment with rocket

lib.rs

#![allow(unused)]
fn main() {
pub mod file_upload_server{
use log::info;
use rocket::{Data, post, routes, Rocket, get, response::content::Json};
use rocket_contrib::serve::StaticFiles;
use std::{fs, path::PathBuf, net::{IpAddr, SocketAddr}};

#[allow(warnings)]
#[post("/", data = "<data>")]
fn upload(data: Data) -> Result<Json<&'static str>, std::io::Error> {
    let path = "./stream.data";
    let pathbuf = PathBuf::from(path);
    if pathbuf.exists() {
        fs::remove_file(pathbuf.clone()).unwrap();
    }
    let mut file = fs::File::create(path)?;

    data.stream_to_file(path)
        .map(|n| format!("Wrote {} bytes to stream.data", n)).unwrap();

    if let Ok(buf) = fs::read(path) {
        if !buf.starts_with(&[0x2D,0x2D,0x2D,0x2D,0x2D,0x2D]){
        if let Some(ex) = get_file_extension(&buf) {
            fs::copy(path, format!("./stream.{}", ex)).unwrap();
        } else {
            fs::copy(path, format!("./stream")).unwrap();
        }
        }else{
          use doe::*;
        let mut buf = buf.clone();
        let remove_last = buf.split_at(buf.len()-46).0.to_vec();
        let remove_first_contet = remove_last.split_at(97).1;
        let (head,other) = remove_first_contet.split_at(200);
        let s = vec_element_to_string!(head).join(":");
        let file_name = vec_element_clone!(split_to_vec!(String::from_utf8_lossy(head),"\""),0);
        let s = split_to_vec!(s,":13:10:13:10:").last().unwrap().to_string();
        let mut s_vec = split_to_vec!(s,":").into_iter().filter(|s|!s.is_empty()).map(|s|s.trim().to_string().parse::<u8>().unwrap()).collect::<Vec<u8>>();
        s_vec.extend(other.iter());
        std::fs::write(file_name, s_vec).unwrap();
        }
    }
    if pathbuf.exists() {
        fs::remove_file(pathbuf).unwrap();
    }
    Ok(Json("{\"status\":\"Ok\"}"))
}

  #[allow(warnings)]
  use rocket::response::{content, Content};
  use rocket::http::ContentType;

  #[get("/")]
  fn index() -> Content<&'static str> {
      let content_type = ContentType::HTML;
      let body = include_str!("./html/index.html");
      Content(content_type, body)
  }

  #[allow(warnings)]
  fn get_file_extension(data: &[u8]) -> Option<&'static str> {
    let ext = match data[..] {
        // Windows PE 可执行文件
        [b'M', b'Z', ..] => Some("exe"),
        // Linux ELF 可执行文件
        [0x7f, b'E', b'L', b'F', ..] => Some("elf"),
        // PNG 图像文件
        [b'\x89', b'P', b'N', b'G', ..] => Some("png"),
        // HTML 文档
        [b'<', b'!', b'D', b'O', b'C', b'T', ..] => Some("html"),
        // PDF 文件
        [b'%', b'P', b'D', b'F', ..] => Some("pdf"),
        // ZIP 压缩文件
        [b'P', b'K', 3, 4, ..] => Some("zip"),
        // 7z 压缩文件
        [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c, ..] => Some("7z"),
        // RAR 压缩文件
        [b'R', b'a', b'r', b'!', ..] => Some("rar"),
        // GZIP 压缩文件
        [b'\x1f', b'\x8b', 8, 0, ..] => Some("gz"),
        // BZIP2 压缩文件
        [b'B', b'Z', b'h', ..] => Some("bz2"),
        // CPIO 归档文件
        [b'I', b's', b'c', b'(', ..] => Some("cpio"),
        // TAR 归档文件
        [b'u', b's', b't', b'a', b'r', ..] => Some("tar"),
        // CHM 帮助文件
        [b'I', b'T', b'S', b'F', ..] => Some("chm"),
        // MP3 音频文件
        [b'I', b'D', b'3', ..] => Some("mp3"),
        // AVI 视频文件
        [b'R', b'I', b'F', b'F', ..] => Some("avi"),
        // JPEG/JFIF 图像文件
        [b'\xff', b'\xd8', b'\xff', ..] => Some("jpg"),
        // BMP 图像文件
        [b'B', b'M', ..] => Some("bmp"),
        // ICO 图标文件
        [0, 1, ..] => Some("ico"),
        // WAV 音频文件
        [b'R', b'I', b'F', b'F', ..] => Some("wav"),
        // Ogg 容器
        [b'O', b'g', b'g', b'S', ..] => Some("ogg"),
        // FLAC 音频文件
        [b'f', b'L', b'a', b'C', ..] => Some("flac"),
        // Impress 演示文稿
        [b'I', b'M', b'P', b'S', ..] => Some("impress"),
        // MIDI 文件
        [b'M', b'T', b'h', b'd', ..] => Some("midi"),
        // TIFF 图像文件
        [b'M', b'M', 0, 42, ..] => Some("tiff"),
        // CR2 图像文件
        [b'I', b'I', 0x2a, 0, 0x10, 0, 0, 0, b'C', b'R', ..] => Some("cr2"),
        // NEF 图像文件
        [b'M', b'M', 0, 0x2a, ..] => Some("nef"),
        // WebP 图像文件
        [b'W', b'E', b'B', b'P', ..] => Some("webp"),
        // Cab 归档文件
        [b'M', b'S', b'C', b'F', ..] => Some("cab"),
        // Microsoft Office Open XML 文档
        [b'P', b'K', 3, 4, ..] => Some("xlsx"),
        // XZ 压缩格式
        [b'\xfd', b'7', b'z', b'X', b'Z', 0, ..] => Some("xz"),
        // iCalendar 文档
        [b'B', b'E', b'G', b'I', b'N', b':', b'V', b'C', ..] => Some("ics"),
        // vCard 文档
        [b'B', b'E', b'G', b'I', b'N', b':', b'V', b'C', b'A', b'R', b'D', ..] => Some("vcf"),
        // SQLite 数据库文件
        [b'S', b'Q', b'L', b'i', b't', b'e', b' ', b'f', b'o', b'r', b'm', b'a', b't', b' ', b'3', ..] => Some("sqlite"),
        // GIF 图像文件
        [b'G', b'I', b'F', b'8', b'7', b'a', ..] |
        [b'G', b'I', b'F', b'8', b'9', b'a', ..] => Some("gif"),

        _ => None,
    };
    ext
}
  pub async fn start() {
    let ip_addr: IpAddr =  match local_ipaddress::get() {
      Some(x)=>{
          x.parse().expect("Found local IP Address is invalid")
        },
        None=>IpAddr::from([127, 0, 0, 1])
    };
    use rocket::config::{Config, Environment};

    let socket_addr = SocketAddr::from((ip_addr, 8585));
    info!("Server listening on http://{}", socket_addr);
    let config = Config::build(Environment::Production)
    .address(socket_addr.ip().to_string())  // 设置应用程序监听地址
    .port(socket_addr.port())            // 设置应用程序监听端口
    .finalize()
    .unwrap();

    Rocket::custom(config)
    .mount("/", StaticFiles::from("static"))
    .mount("/", routes![upload,index])
    .launch();
  }

}
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>File Upload</title>
</head>
<style>
  h1 {
  text-align: center;
}

form {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-top: 50px;
}

input[type=file] {
  margin-bottom: 20px;
  font-size: 16px;
  padding: 10px;
  border-radius: 5px;
  background-color: #f2f2f2;
  border: none;
}

button[type=submit] {
  padding: 10px 20px;
  background-color: #4CAF50;
  color: #fff;
  border: none;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
}

#message {
  display: none; /* 初始时隐藏 */
  width: 100%;
  padding: 20px;
  background-color: #4CAF50;
  color: #fff;
  text-align: center;
  margin-top: 50px;
}

</style>
<body>
  <h1>File Upload</h1>
  <form method="post" action="/" enctype="application/x-www-form-urlencoded">
    <input type="file" name="file">
    <button type="submit">Upload</button>
  </form>
  <div id="message"></div> <!-- 显示上传成功信息的 div -->
</body>
<script>
  const form = document.querySelector('form');
const message = document.querySelector('#message');

form.addEventListener('submit', (event) => {
    event.preventDefault();
    const fileInput = document.querySelector('input[type=file]');
    const files = fileInput.files;
    if (files.length === 0) {
        alert('Please select a file!');
        return;
    }
    const formData = new FormData();
    formData.append('file', files[0]);
    fetch('/', { method: 'POST', body: formData })
      .then(response => response.json())
      .then(data => {
          if (data.status) {
              showSuccessMessage();
          } else {
              alert(data.message);
          }
      });
});

function showSuccessMessage() {
    message.innerHTML = 'File uploaded successfully!';
    message.style.display = 'block';
    setTimeout(() => {
    message.style.display = 'none';
  }, 3000); // 3秒后自动隐藏提示信息
}
</script>
</html>