67 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use crate::app_config::AppConfig;
 | 
						|
use crate::server::custom_error::HttpResult;
 | 
						|
use crate::utils::time_utils::current_day;
 | 
						|
use actix_web::HttpResponse;
 | 
						|
use anyhow::Context;
 | 
						|
use std::fs::File;
 | 
						|
use std::io::{Cursor, Read, Write};
 | 
						|
use walkdir::WalkDir;
 | 
						|
use zip::write::SimpleFileOptions;
 | 
						|
 | 
						|
/// Download a full copy of the storage data
 | 
						|
pub async fn download_storage() -> HttpResult {
 | 
						|
    let mut zip_buff = Cursor::new(Vec::new());
 | 
						|
    let mut zip = zip::ZipWriter::new(&mut zip_buff);
 | 
						|
 | 
						|
    let options = SimpleFileOptions::default()
 | 
						|
        .compression_method(zip::CompressionMethod::Bzip2)
 | 
						|
        .unix_permissions(0o700);
 | 
						|
 | 
						|
    let storage = AppConfig::get().storage_path();
 | 
						|
 | 
						|
    let mut file_buff = Vec::new();
 | 
						|
    for entry in WalkDir::new(&storage) {
 | 
						|
        let entry = entry?;
 | 
						|
 | 
						|
        let path = entry.path();
 | 
						|
        let name = path.strip_prefix(&storage).unwrap();
 | 
						|
        let path_as_string = name
 | 
						|
            .to_str()
 | 
						|
            .map(str::to_owned)
 | 
						|
            .with_context(|| format!("{name:?} Is a Non UTF-8 Path"))?;
 | 
						|
 | 
						|
        // Write file or directory explicitly
 | 
						|
        // Some unzip tools unzip files with directory paths correctly, some do not!
 | 
						|
        if path.is_file() {
 | 
						|
            log::debug!("adding file {path:?} as {name:?} ...");
 | 
						|
            zip.start_file(path_as_string, options)?;
 | 
						|
            let mut f = File::open(path)?;
 | 
						|
 | 
						|
            f.read_to_end(&mut file_buff)?;
 | 
						|
            zip.write_all(&file_buff)?;
 | 
						|
            file_buff.clear();
 | 
						|
        } else if !name.as_os_str().is_empty() {
 | 
						|
            // Only if not root! Avoids path spec / warning
 | 
						|
            // and mapname conversion failed error on unzip
 | 
						|
            log::debug!("adding dir {path_as_string:?} as {name:?} ...");
 | 
						|
            zip.add_directory(path_as_string, options)?;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // Inject runtime configuration
 | 
						|
    zip.start_file("/app_config.json", options)?;
 | 
						|
    zip.write_all(&serde_json::to_vec_pretty(&AppConfig::get())?)?;
 | 
						|
 | 
						|
    zip.finish()?;
 | 
						|
 | 
						|
    let filename = format!("storage-{}.zip", current_day());
 | 
						|
 | 
						|
    Ok(HttpResponse::Ok()
 | 
						|
        .content_type("application/zip")
 | 
						|
        .insert_header((
 | 
						|
            "content-disposition",
 | 
						|
            format!("attachment; filename=\"{filename}\""),
 | 
						|
        ))
 | 
						|
        .body(zip_buff.into_inner()))
 | 
						|
}
 |