Can export family data

This commit is contained in:
2023-08-17 17:37:44 +02:00
parent 680c2d2624
commit 3b5efb46cd
7 changed files with 224 additions and 6 deletions

View File

@ -0,0 +1,58 @@
use crate::connections::s3_connection;
use crate::controllers::HttpResult;
use crate::extractors::family_extractor::FamilyInPath;
use crate::services::{couples_service, members_service, photos_service};
use actix_web::HttpResponse;
use std::io::{Cursor, Write};
use zip::write::FileOptions;
use zip::CompressionMethod;
const MEMBERS_FILE: &str = "members.json";
const COUPLES_FILE: &str = "couples.json";
/// Export whole family data
pub async fn export_family(f: FamilyInPath) -> HttpResult {
let files_opt = FileOptions::default().compression_method(CompressionMethod::Bzip2);
let members = members_service::get_all_of_family(f.family_id()).await?;
let couples = couples_service::get_all_of_family(f.family_id()).await?;
let buff = Vec::with_capacity(1000000);
let mut zip_file = zip::ZipWriter::new(Cursor::new(buff));
// Add main files
zip_file.start_file(MEMBERS_FILE, files_opt)?;
zip_file.write_all(serde_json::to_string(&members)?.as_bytes())?;
zip_file.start_file(COUPLES_FILE, files_opt)?;
zip_file.write_all(serde_json::to_string(&couples)?.as_bytes())?;
// Add photos
let mut photos = Vec::new();
for member in &members {
if let Some(id) = member.photo_id() {
photos.push(id);
}
}
for couple in &couples {
if let Some(id) = couple.photo_id() {
photos.push(id);
}
}
for id in photos {
let photo = photos_service::get_by_id(id).await?;
let ext = photo.mime_extension().unwrap_or("bad");
let file = s3_connection::get_file(&photo.photo_path()).await?;
zip_file.start_file(format!("photos/{}.{ext}", id.0), files_opt)?;
zip_file.write_all(&file)?;
}
let buff = zip_file.finish()?.into_inner();
Ok(HttpResponse::Ok()
.content_type("application/zip")
.body(buff))
}

View File

@ -3,9 +3,11 @@
use actix_web::body::BoxBody;
use actix_web::HttpResponse;
use std::fmt::{Debug, Display, Formatter};
use zip::result::ZipError;
pub mod auth_controller;
pub mod couples_controller;
pub mod data_controller;
pub mod families_controller;
pub mod members_controller;
pub mod photos_controller;
@ -37,4 +39,22 @@ impl From<anyhow::Error> for HttpErr {
}
}
impl From<ZipError> for HttpErr {
fn from(value: ZipError) -> Self {
HttpErr { err: value.into() }
}
}
impl From<serde_json::Error> for HttpErr {
fn from(value: serde_json::Error) -> Self {
HttpErr { err: value.into() }
}
}
impl From<std::io::Error> for HttpErr {
fn from(value: std::io::Error) -> Self {
HttpErr { err: value.into() }
}
}
pub type HttpResult = Result<HttpResponse, HttpErr>;

View File

@ -6,7 +6,7 @@ use actix_web::{web, App, HttpServer};
use geneit_backend::app_config::AppConfig;
use geneit_backend::connections::s3_connection;
use geneit_backend::controllers::{
auth_controller, couples_controller, families_controller, members_controller,
auth_controller, couples_controller, data_controller, families_controller, members_controller,
photos_controller, server_controller, users_controller,
};
@ -191,6 +191,11 @@ async fn main() -> std::io::Result<()> {
"/family/{id}/couple/{couple_id}/photo",
web::delete().to(couples_controller::remove_photo),
)
// Data controller
.route(
"/family/{id}/data/export",
web::get().to(data_controller::export_family),
)
// Photos controller
.route(
"/photo/{id}",

View File

@ -168,6 +168,13 @@ impl Photo {
pub fn thumbnail_path(&self) -> String {
format!("thumbnail/{}", self.file_id)
}
pub fn mime_extension(&self) -> Option<&str> {
mime_guess::get_mime_extensions_str(&self.mime_type)
.map(|e| e.first())
.unwrap_or_default()
.copied()
}
}
#[derive(Insertable)]