diff --git a/src/modes/server/api/item.rs b/src/modes/server/api/item.rs index 20bb860..14fd5fa 100644 --- a/src/modes/server/api/item.rs +++ b/src/modes/server/api/item.rs @@ -179,7 +179,7 @@ pub async fn handle_get_item_latest_content( match item_with_meta { Ok(item) => { let item_id = item.item.id.unwrap(); - match stream_item_content(&item_service, item_id, params.allow_binary, params.offset, params.length).await { + match item_service.stream_item_content_by_id(item_id, params.allow_binary, params.offset, params.length).await { Ok((stream, mime_type)) => { let body = axum::body::Body::from_stream(stream); let response = Response::builder() @@ -202,57 +202,6 @@ pub async fn handle_get_item_latest_content( } } -async fn stream_item_content( - service: &AsyncItemService, - item_id: i64, - allow_binary: bool, - offset: u64, - length: u64, -) -> anyhow::Result<(impl tokio_stream::Stream>, String)> { - let item_with_content = service.get_item_content(item_id).await?; - let metadata = item_with_content.item_with_meta.meta_as_map(); - - // Check if content is binary when allow_binary is false - if !allow_binary { - let is_content_binary = if let Some(binary_val) = metadata.get("binary") { - binary_val == "true" - } else { - // If binary metadata not available, check the actual content - is_binary(&item_with_content.content) - }; - - if is_content_binary { - return Err(anyhow::anyhow!("Binary content not allowed")); - } - } - - let mime_type = metadata - .get("mime_type") - .map(|s| s.to_string()) - .unwrap_or_else(|| "application/octet-stream".to_string()); - - // Open the file for streaming - let file_path = service.data_dir.join(format!("{}.dat", item_id)); - let file = tokio::fs::File::open(&file_path).await?; - let mut buffered_file = tokio::io::BufReader::new(file); - - // Seek to the requested offset if needed - if offset > 0 { - buffered_file.seek(std::io::SeekFrom::Start(offset)).await?; - } - - // Create a reader stream with optional length limit - // Create a reader stream with optional length limit - let stream = if length > 0 { - // Limit the stream to the specified length - Box::pin(ReaderStream::new(buffered_file.take(length))) as std::pin::Pin> + Send>> - } else { - // Stream the entire file from the offset - Box::pin(ReaderStream::new(buffered_file)) as std::pin::Pin> + Send>> - }; - - Ok((stream, mime_type)) -} #[utoipa::path( get, @@ -290,7 +239,7 @@ pub async fn handle_get_item_content( let item_service = AsyncItemService::new(state.data_dir.clone(), state.db.clone()); - match stream_item_content(&item_service, item_id, params.allow_binary, params.offset, params.length).await { + match item_service.stream_item_content_by_id(item_id, params.allow_binary, params.offset, params.length).await { Ok((stream, mime_type)) => { let body = axum::body::Body::from_stream(stream); let response = Response::builder() diff --git a/src/services/async_item_service.rs b/src/services/async_item_service.rs index 6b94b78..485b1f5 100644 --- a/src/services/async_item_service.rs +++ b/src/services/async_item_service.rs @@ -104,6 +104,57 @@ impl AsyncItemService { Ok((stream, mime_type)) } + pub async fn stream_item_content_by_id( + &self, + item_id: i64, + allow_binary: bool, + offset: u64, + length: u64, + ) -> anyhow::Result<(impl tokio_stream::Stream>, String)> { + let item_with_content = self.get_item_content(item_id).await?; + let metadata = item_with_content.item_with_meta.meta_as_map(); + + // Check if content is binary when allow_binary is false + if !allow_binary { + let is_content_binary = if let Some(binary_val) = metadata.get("binary") { + binary_val == "true" + } else { + // If binary metadata not available, check the actual content + is_binary(&item_with_content.content) + }; + + if is_content_binary { + return Err(anyhow::anyhow!("Binary content not allowed")); + } + } + + let mime_type = metadata + .get("mime_type") + .map(|s| s.to_string()) + .unwrap_or_else(|| "application/octet-stream".to_string()); + + // Open the file for streaming + let file_path = self.data_dir.join(format!("{}.dat", item_id)); + let file = tokio::fs::File::open(&file_path).await?; + let mut buffered_file = tokio::io::BufReader::new(file); + + // Seek to the requested offset if needed + if offset > 0 { + buffered_file.seek(std::io::SeekFrom::Start(offset)).await?; + } + + // Create a reader stream with optional length limit + let stream = if length > 0 { + // Limit the stream to the specified length + Box::pin(ReaderStream::new(buffered_file.take(length))) as std::pin::Pin> + Send>> + } else { + // Stream the entire file from the offset + Box::pin(ReaderStream::new(buffered_file)) as std::pin::Pin> + Send>> + }; + + Ok((stream, mime_type)) + } + pub async fn find_item( &self, ids: Vec,