fix(nextcloud): detect MIME type via magic bytes instead of trusting client header

Nextcloud app uploads sent application/octet-stream as Content-Type,
causing images to not be recognized. Now both WebDAV PUT and chunked
upload paths call refine_content_type() which detects via magic bytes,
then extension, then falls back to the client header. Also fixes
update_file() which previously hardcoded application/octet-stream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zjean
2026-03-04 15:51:47 +01:00
parent 40b269c4eb
commit fdbb144cd8
6 changed files with 163 additions and 15 deletions
+7 -2
View File
@@ -20,6 +20,7 @@ use crate::application::ports::file_ports::{
use crate::application::ports::inbound::FolderUseCase;
use crate::application::ports::trash_ports::TrashUseCase;
use crate::common::di::AppState;
use crate::common::mime_detect::{filename_from_path, refine_content_type};
use crate::interfaces::errors::AppError;
use crate::interfaces::middleware::auth::CurrentUser;
@@ -472,7 +473,7 @@ async fn handle_put(
let file_service = &state.applications.file_retrieval_service;
let upload_service = &state.applications.file_upload_service;
let content_type = req
let claimed_type = req
.headers()
.get(header::CONTENT_TYPE)
.and_then(|v| v.to_str().ok())
@@ -490,13 +491,17 @@ async fn handle_put(
.await
.map_err(|e| AppError::bad_request(format!("Failed to read body: {}", e)))?;
// Detect real MIME type via magic bytes + extension, falling back to client header.
let filename = filename_from_path(subpath);
let content_type = refine_content_type(&body_bytes, filename, &claimed_type);
// Check if the file already exists (update vs create).
let existing = file_service.get_file_by_path(&internal_path).await;
if existing.is_ok() {
// Update existing file.
upload_service
.update_file(&internal_path, &body_bytes)
.update_file(&internal_path, &body_bytes, &content_type)
.await
.map_err(|e| AppError::internal_error(format!("Failed to update file: {}", e)))?;