Advertisement
aircampro

rust tide file upload

Nov 27th, 2023
5,011
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 8.42 KB | Software | 0 0
  1. // Rust file server (Linux)
  2. // In this example you can upload and download files make a log of last download and view it
  3. // also you can invoke system commands and print the results as HTML
  4. //
  5. // ===== Cargo.toml =====
  6. // [dependencies]
  7. // tide = "0.16.0"
  8. // async-std = { version = "1.6.0", features = ["attributes"] }
  9. // serde = { version = "1.0", features = ["derive"] }
  10. // tempfile = "3.5.0"
  11. // csv = "1.1"
  12. // chrono = { version = "0.4", features = ["serde"] }
  13. //
  14. use std::io::Error as IoError;
  15. use std::path::Path;
  16. use std::sync::Arc;
  17.  
  18. use async_std::{fs::OpenOptions, io};
  19. use tempfile::TempDir;
  20. use tide::prelude::*;
  21. use tide::{Body, Request, Response, StatusCode, Redirect};
  22.  
  23. use std::{env};
  24. use std::fs::File;
  25. use std::path::PathBuf;
  26. use csv::Writer;
  27.  
  28. use chrono::{Utc, Local, DateTime, Date};
  29.  
  30. use std::process::Command;
  31.  
  32. #[derive(Clone)]
  33. struct TempDirState {
  34.     tempdir: Arc<TempDir>,
  35. }
  36.  
  37. impl TempDirState {
  38.     fn try_new() -> Result<Self, IoError> {
  39.         Ok(Self {
  40.             tempdir: Arc::new(tempfile::tempdir()?),
  41.         })
  42.     }
  43.  
  44.     fn path(&self) -> &Path {
  45.         self.tempdir.path()
  46.     }
  47. }
  48.  
  49. #[async_std::main]
  50. async fn main() -> Result<(), IoError> {
  51.    
  52.     let mut app = tide::with_state(TempDirState::try_new()?);
  53.     app.with(tide::log::LogMiddleware::new());
  54.  
  55.  
  56.     app.at(":file")
  57.         // $ curl -T ./a.txt localhost:8080 # this writes the file to a temp directory
  58.         //
  59.         .put(|req: Request<TempDirState>| async move {
  60.             let path = req.param("file")?;
  61.             let p = req.param("file").unwrap().to_string();
  62.             let fs_path = req.state().path().join(path);
  63.  
  64.             let file = OpenOptions::new()
  65.                 .create(true)
  66.                 .write(true)
  67.                 .open(&fs_path)
  68.                 .await?;
  69.  
  70.             let bytes_written = io::copy(req, file).await?;
  71.             println!("file written bytes {}", bytes_written);
  72.              let export_folder = env::var("EXPORT_FOLDER").map_err(|_| {
  73.                  io::Error::new(io::ErrorKind::NotFound, "set env variable EXPORT_FOLDER to export path")
  74.              })?;
  75.  
  76.              // write to a csv the file and time we downloaded it
  77.              let file_path = PathBuf::from(export_folder).join("input.csv");
  78.              
  79.              let utc_datetime: DateTime<Utc> = Utc::now();
  80.              println!("{}", utc_datetime);
  81.  
  82.              let file = File::create(&file_path)?;
  83.              let mut writer = Writer::from_writer(file);
  84.              let f_desc = "file uploaded was ".to_string();
  85.              let text = Utc::now().format("%Y-%m-%d %H:%M:%S:%Z").to_string();
  86.              let records = vec![
  87.                  vec![&f_desc, &p, &text],
  88.              ];
  89.              for record in records {
  90.                     writer.write_record(record)?;
  91.              }  
  92.              writer.flush()?;
  93.              
  94.             Ok(json!({ "bytes": bytes_written }))
  95.         })
  96.         // $ curl localhost:8080/a.txt # this reads the file from the same temp directory and logs it to a file
  97.         //
  98.         .get(|req: Request<TempDirState>| async move {
  99.              let path = req.param("file")?;
  100.              let p = req.param("file").unwrap().to_string();
  101.              let fs_path = req.state().path().join(path);
  102.              
  103.              let export_folder = env::var("EXPORT_FOLDER").map_err(|_| {
  104.                  io::Error::new(io::ErrorKind::NotFound, "set env variable EXPORT_FOLDER to export path")
  105.              })?;
  106.  
  107.              // write to a csv the file and time we downloaded it
  108.              let file_path = PathBuf::from(export_folder).join("output.csv");
  109.              
  110.              let utc_datetime: DateTime<Utc> = Utc::now();
  111.              println!("{}", utc_datetime);
  112.              
  113.              if let Ok(body) = Body::from_file(fs_path).await {
  114.              let file = File::create(&file_path)?;
  115.              let mut writer = Writer::from_writer(file);
  116.              let f_desc = "file downloaded was ".to_string();
  117.              let text = Utc::now().format("%Y-%m-%d %H:%M:%S:%Z").to_string();
  118.              let records = vec![
  119.                  vec![&f_desc, &p, &text],
  120.              ];
  121.              for record in records {
  122.                     writer.write_record(record)?;
  123.              }  
  124.              writer.flush()?;
  125.  
  126.              Ok(body.into())
  127.             } else {
  128.                 Ok(Response::new(StatusCode::NotFound))
  129.             }
  130.         });
  131.         // curl localhost:8080/showlastdownload
  132.         //      
  133.         app.at("/showlastdownload").get(|_req: Request<TempDirState>| async move {
  134.              let export_folder = env::var("EXPORT_FOLDER").map_err(|_| {
  135.                  io::Error::new(io::ErrorKind::NotFound, "set env variable EXPORT_FOLDER to export path")
  136.              })?;
  137.  
  138.              // write to a csv the file and time we downloaded it
  139.              let file_path = PathBuf::from(export_folder).join("output.csv");
  140.              let output = Command::new("/bin/cat")
  141.                      //.arg("/home/mark/enfile/output.csv") <---- if you dont want to use the env variable
  142.                      .arg(&file_path)
  143.                      .output()
  144.                      .expect("failed to execute process");
  145.             println!("status: {}", output.status);
  146.             println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
  147.             println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
  148.             Ok(tide::Response::builder(200)
  149.                  .body(format!("<html><h2>Download csv :-, {}!</h2></html>",
  150.                   String::from_utf8_lossy(&output.stdout)))
  151.                  .header("Server", "tide")
  152.                  .content_type(tide::http::mime::HTML)
  153.                  .build())
  154.         });  
  155.         // curl localhost:8080/showlastupload
  156.         //  
  157.         app.at("/showlastupload").get(|_req: Request<TempDirState>| async move {
  158.              let export_folder = env::var("EXPORT_FOLDER").map_err(|_| {
  159.                  io::Error::new(io::ErrorKind::NotFound, "set env variable EXPORT_FOLDER to export path")
  160.              })?;
  161.  
  162.              // write to a csv the file and time we downloaded it
  163.              let file_path = PathBuf::from(export_folder).join("input.csv");
  164.              let output = Command::new("/bin/cat")
  165.                      //.arg("/home/mark/enfile/input.csv") <---- if you dont want to use the env variable
  166.                      .arg(&file_path)
  167.                      .output()
  168.                      .expect("failed to execute process");
  169.             println!("status: {}", output.status);
  170.             println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
  171.             println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
  172.             Ok(tide::Response::builder(200)
  173.                  .body(format!("<html><h2>Upload csv :-, {}!</h2></html>",
  174.                   String::from_utf8_lossy(&output.stdout)))
  175.                  .header("Server", "tide")
  176.                  .content_type(tide::http::mime::HTML)
  177.                  .build())
  178.         });
  179.         // shows the contents of the EXPORT_FOLDER variable
  180.         // e.g. EXPORT_FOLDER=/usr/nik/myfles; export EXPORT_FOLDER
  181.         // curl localhost:8080/showdirectory
  182.         //  
  183.         app.at("/showdirectory").get(|_req: Request<TempDirState>| async move {
  184.             //let dname = req.param("dir").unwrap().to_string();
  185.              let export_folder = env::var("EXPORT_FOLDER").map_err(|_| {
  186.                  io::Error::new(io::ErrorKind::NotFound, "set env variable EXPORT_FOLDER to export path")
  187.              })?;
  188.             let output = Command::new("/bin/ls")
  189.                .args(&["-l", "-a", &export_folder])
  190.                .output()
  191.                .expect("failed to start `ls`");
  192.             println!("status: {}", output.status);
  193.             println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
  194.             println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
  195.             Ok(tide::Response::builder(200)
  196.                  .body(format!("<html><h2>Download csv :-, {}!</h2></html>",
  197.                   String::from_utf8_lossy(&output.stdout)))
  198.                  .header("Server", "tide")
  199.                  .content_type(tide::http::mime::HTML)
  200.                  .build())
  201.         });
  202.         // curl localhost:8080/rd
  203.         //
  204.         app.at("/rd")
  205.            .get(Redirect::new("https://www.youtube.com/watch?v=GGk_KrRyXLo"));
  206.     app.listen("127.0.0.1:8080").await?;
  207.     Ok(())
  208. }
  209.  
Tags: #rust #tide
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement