Can export family data
This commit is contained in:
58
geneit_backend/src/controllers/data_controller.rs
Normal file
58
geneit_backend/src/controllers/data_controller.rs
Normal 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))
|
||||
}
|
@ -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>;
|
||||
|
@ -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}",
|
||||
|
@ -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)]
|
||||
|
Reference in New Issue
Block a user