Can export data as ZIP file

This commit is contained in:
2025-05-02 23:24:38 +02:00
parent 1b3ce1a98d
commit f335b9d0c0
6 changed files with 321 additions and 8 deletions

View File

@ -1,3 +1,5 @@
use crate::app_config::AppConfig;
use crate::constants;
use crate::controllers::HttpResult;
use crate::converters::finances_manager_converter::{
FinancesManagerAccount, FinancesManagerFile, FinancesManagerMovement,
@ -7,9 +9,23 @@ use crate::extractors::file_extractor::FileExtractor;
use crate::models::accounts::AccountType;
use crate::services::accounts_service::UpdateAccountQuery;
use crate::services::movements_service::UpdateMovementQuery;
use crate::services::{accounts_service, movements_service};
use crate::services::{accounts_service, files_service, movements_service};
use crate::utils::time_utils::{format_date, time};
use actix_web::HttpResponse;
use actix_files::NamedFile;
use actix_web::{HttpRequest, HttpResponse};
use serde::Serialize;
use std::fs::File;
use std::io::Write;
use zip::ZipWriter;
use zip::write::SimpleFileOptions;
/// Generate export filename
fn export_filename(ext: &str) -> String {
format!(
"export_{}.{ext}",
format_date(time() as i64).unwrap().replace('/', "-")
)
}
/// Import data from a [FinancesManager](https://gitlab.com/pierre42100/cpp-financesmanager) file
pub async fn finances_manager_import(auth: AuthExtractor, file: FileExtractor) -> HttpResult {
@ -69,10 +85,71 @@ pub async fn finances_manager_export(auth: AuthExtractor) -> HttpResult {
Ok(HttpResponse::Ok()
.insert_header((
"Content-Disposition",
format!(
"attachment; filename=export_{}.finance",
format_date(time() as i64)?.replace('/', "-")
),
format!("attachment; filename={}", export_filename("finance")),
))
.body(out.encode()))
}
/// Add JSON file to ZIP
fn zip_json<E: Serialize>(
zip: &mut ZipWriter<File>,
path: &str,
content: &E,
) -> anyhow::Result<()> {
let file_encoded = serde_json::to_string(&content)?;
let options = SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Deflated)
.unix_permissions(0o750);
zip.start_file(path, options)?;
zip.write_all(file_encoded.as_bytes())?;
Ok(())
}
/// Export all user data as ZIP
pub async fn zip_export(req: HttpRequest, auth: AuthExtractor) -> HttpResult {
let dest_dir = tempfile::tempdir_in(&AppConfig::get().temp_dir)?;
let zip_path = dest_dir.path().join("export.zip");
let file = File::create(&zip_path)?;
let mut zip = ZipWriter::new(file);
// Process all JSON documents
zip_json(
&mut zip,
constants::zip_export::ACCOUNTS_FILE,
&accounts_service::get_list_user(auth.user_id()).await?,
)?;
zip_json(
&mut zip,
constants::zip_export::MOVEMENTS_FILE,
&movements_service::get_all_movements_user(auth.user_id()).await?,
)?;
let files_list = files_service::get_all_files_user(auth.user_id()).await?;
zip_json(&mut zip, constants::zip_export::FILES_FILE, &files_list)?;
// TODO : inbox
// Process all files
for file in files_list {
let buff = files_service::get_file_content(&file).await?;
let options = SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Deflated)
.unix_permissions(0o750);
zip.start_file(
format!("{}{}", constants::zip_export::FILES_DIR, file.sha512),
options,
)?;
zip.write_all(&buff)?;
}
// Finalize ZIP and return response
zip.finish()?;
let file = File::open(zip_path)?;
let file = NamedFile::from_file(file, export_filename("zip"))?;
Ok(file.into_response(&req))
}