mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 18:32:12 +00:00
Fixed an unreadable sheet silently dropping the remaining sheets of a spreadsheet
This commit is contained in:
parent
ed93308036
commit
47059352f1
@ -8,7 +8,7 @@ use axum::extract::Query;
|
|||||||
use axum::extract::rejection::QueryRejection;
|
use axum::extract::rejection::QueryRejection;
|
||||||
use axum::response::sse::{Event, Sse};
|
use axum::response::sse::{Event, Sse};
|
||||||
use base64::{engine::general_purpose, Engine as _};
|
use base64::{engine::general_purpose, Engine as _};
|
||||||
use calamine::{open_workbook_auto, Reader};
|
use calamine::{open_workbook_auto, Error as CalamineError, Reader};
|
||||||
use file_format::{FileFormat, Kind};
|
use file_format::{FileFormat, Kind};
|
||||||
use futures::{Stream, StreamExt};
|
use futures::{Stream, StreamExt};
|
||||||
use pdfium_render::prelude::{Pdfium, PdfiumError, PdfiumInternalError};
|
use pdfium_render::prelude::{Pdfium, PdfiumError, PdfiumInternalError};
|
||||||
@ -95,6 +95,7 @@ pub enum ExtractionErrorCode {
|
|||||||
FileNotReadable,
|
FileNotReadable,
|
||||||
FormatDetectionFailed,
|
FormatDetectionFailed,
|
||||||
NotAValidPdf,
|
NotAValidPdf,
|
||||||
|
NotAValidSpreadsheet,
|
||||||
PdfiumUnavailable,
|
PdfiumUnavailable,
|
||||||
PdfEncrypted,
|
PdfEncrypted,
|
||||||
PageExtractionFailed,
|
PageExtractionFailed,
|
||||||
@ -585,6 +586,15 @@ async fn stream_pdf(file_path: &str) -> Result<ChunkStream> {
|
|||||||
Ok(Box::pin(ReceiverStream::new(rx)))
|
Ok(Box::pin(ReceiverStream::new(rx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Classifies a spreadsheet failure, so an unreadable file, e.g. on a network share which went
|
||||||
|
/// away, is not reported as a corrupt workbook.
|
||||||
|
fn classify_spreadsheet_error_code(error: &CalamineError) -> ExtractionErrorCode {
|
||||||
|
match error {
|
||||||
|
CalamineError::Io(_) => ExtractionErrorCode::FileNotReadable,
|
||||||
|
_ => ExtractionErrorCode::NotAValidSpreadsheet,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn stream_spreadsheet_as_csv(file_path: &str) -> Result<ChunkStream> {
|
async fn stream_spreadsheet_as_csv(file_path: &str) -> Result<ChunkStream> {
|
||||||
let path = file_path.to_owned();
|
let path = file_path.to_owned();
|
||||||
let (tx, rx) = mpsc::channel(10);
|
let (tx, rx) = mpsc::channel(10);
|
||||||
@ -593,7 +603,10 @@ async fn stream_spreadsheet_as_csv(file_path: &str) -> Result<ChunkStream> {
|
|||||||
let mut workbook = match open_workbook_auto(&path) {
|
let mut workbook = match open_workbook_auto(&path) {
|
||||||
Ok(w) => w,
|
Ok(w) => w,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = tx.blocking_send(Err(e.into()));
|
let _ = tx.blocking_send(Err(ExtractionError::new(
|
||||||
|
classify_spreadsheet_error_code(&e),
|
||||||
|
format!("The spreadsheet could not be opened: {e}"),
|
||||||
|
).into()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -602,7 +615,20 @@ async fn stream_spreadsheet_as_csv(file_path: &str) -> Result<ChunkStream> {
|
|||||||
let range = match workbook.worksheet_range(&sheet_name) {
|
let range = match workbook.worksheet_range(&sheet_name) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = tx.blocking_send(Err(e.into()));
|
//
|
||||||
|
// One unreadable sheet must not end the workbook: we report it as a non-fatal
|
||||||
|
// error chunk and continue with the next sheet. Sending it as an `Err` would
|
||||||
|
// stop the consumer and silently drop all remaining sheets.
|
||||||
|
//
|
||||||
|
warn!("The sheet '{sheet_name}' of '{path}' could not be read: {e}");
|
||||||
|
|
||||||
|
if tx.blocking_send(Ok(Chunk::from_error(&ExtractionError::new(
|
||||||
|
classify_spreadsheet_error_code(&e),
|
||||||
|
format!("The sheet '{sheet_name}' could not be read: {e}"),
|
||||||
|
)))).is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user