wip: export engine
This commit is contained in:
@@ -167,6 +167,83 @@ pub async fn get_export_jobs(
|
||||
Ok(Json(jobs))
|
||||
}
|
||||
|
||||
// ── Export download endpoints (authenticated guests) ─────────────────────────
|
||||
|
||||
pub async fn download_zip(
|
||||
State(state): State<AppState>,
|
||||
_auth: crate::auth::middleware::AuthUser,
|
||||
) -> Result<axum::response::Response, AppError> {
|
||||
let event = crate::models::event::Event::find_by_slug(&state.pool, &state.config.event_slug)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("Event nicht gefunden.".into()))?;
|
||||
|
||||
if !event.export_zip_ready {
|
||||
return Err(AppError::NotFound(
|
||||
"Der ZIP-Export ist noch nicht verfügbar.".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let path = state.config.media_path.join("exports").join("Gallery.zip");
|
||||
if !path.exists() {
|
||||
return Err(AppError::NotFound("Exportdatei nicht gefunden.".into()));
|
||||
}
|
||||
|
||||
serve_file(path, "Gallery.zip", "application/zip").await
|
||||
}
|
||||
|
||||
pub async fn download_html(
|
||||
State(state): State<AppState>,
|
||||
_auth: crate::auth::middleware::AuthUser,
|
||||
) -> Result<axum::response::Response, AppError> {
|
||||
let event = crate::models::event::Event::find_by_slug(&state.pool, &state.config.event_slug)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("Event nicht gefunden.".into()))?;
|
||||
|
||||
if !event.export_html_ready {
|
||||
return Err(AppError::NotFound(
|
||||
"Der HTML-Export ist noch nicht verfügbar.".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let path = state.config.media_path.join("exports").join("Memories.zip");
|
||||
if !path.exists() {
|
||||
return Err(AppError::NotFound("Exportdatei nicht gefunden.".into()));
|
||||
}
|
||||
|
||||
serve_file(path, "Memories.zip", "application/zip").await
|
||||
}
|
||||
|
||||
async fn serve_file(
|
||||
path: std::path::PathBuf,
|
||||
filename: &str,
|
||||
content_type: &str,
|
||||
) -> Result<axum::response::Response, AppError> {
|
||||
use axum::body::Body;
|
||||
use axum::http::{header, Response, StatusCode};
|
||||
use tokio_util::io::ReaderStream;
|
||||
|
||||
let file = tokio::fs::File::open(&path)
|
||||
.await
|
||||
.map_err(|e| AppError::Internal(e.into()))?;
|
||||
let metadata = file
|
||||
.metadata()
|
||||
.await
|
||||
.map_err(|e| AppError::Internal(e.into()))?;
|
||||
let stream = ReaderStream::new(file);
|
||||
|
||||
let disposition = format!("attachment; filename=\"{filename}\"");
|
||||
|
||||
let response = Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(header::CONTENT_TYPE, content_type)
|
||||
.header(header::CONTENT_DISPOSITION, disposition)
|
||||
.header(header::CONTENT_LENGTH, metadata.len())
|
||||
.body(Body::from_stream(stream))
|
||||
.map_err(|e| AppError::Internal(e.into()))?;
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// Also expose export status to all authenticated users (guests need it for the export page)
|
||||
pub async fn export_status(
|
||||
State(state): State<AppState>,
|
||||
|
||||
Reference in New Issue
Block a user