mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-12 23:02:35 +00:00
fix: await processing end-to-end so replace status check is reliable; settle Firefox picker on cancel
- process_uploaded_file now awaits _process_handler (previously the coroutine was created and discarded), and the inner process_file calls inside _process_handler are awaited too. Without these awaits, uploads with process=True / process_in_background=False returned before processing ever ran, so data.status stayed 'pending' forever — which is exactly why upload_and_replace_file's Step 2 check (status == 'completed') was unreliable for valid files. Fix the upstream root cause instead of polling for status downstream. - Firefox directory-picker fallback in collectDirectoryFiles now always settles its Promise: handlers are consolidated through a single finish() helper, the modern 'cancel' event is wired up, and a window-focus + 500ms sentinel resolves with empty files when the picker dismisses without any event. Without this, cancelling the picker in Firefox left the caller stuck on "Scanning directory..." with no completion path.
This commit is contained in:
parent
a59beeaaf9
commit
1119bf045a
2 changed files with 53 additions and 20 deletions
|
|
@ -115,7 +115,7 @@ async def process_uploaded_file(
|
|||
file_path_processed = Storage.get_file(file_path)
|
||||
result = transcribe(request, file_path_processed, file_metadata, user)
|
||||
|
||||
process_file(
|
||||
await process_file(
|
||||
request,
|
||||
ProcessFileForm(file_id=file_item.id, content=result.get('text', '')),
|
||||
user=user,
|
||||
|
|
@ -124,7 +124,7 @@ async def process_uploaded_file(
|
|||
elif (not content_type.startswith(('image/', 'video/'))) or (
|
||||
request.app.state.config.CONTENT_EXTRACTION_ENGINE == 'external'
|
||||
):
|
||||
process_file(
|
||||
await process_file(
|
||||
request,
|
||||
ProcessFileForm(file_id=file_item.id),
|
||||
user=user,
|
||||
|
|
@ -134,7 +134,7 @@ async def process_uploaded_file(
|
|||
raise Exception(f'File type {content_type} is not supported for processing')
|
||||
else:
|
||||
log.info(f'File type {file.content_type} is not provided, but trying to process anyway')
|
||||
process_file(
|
||||
await process_file(
|
||||
request,
|
||||
ProcessFileForm(file_id=file_item.id),
|
||||
user=user,
|
||||
|
|
@ -153,10 +153,10 @@ async def process_uploaded_file(
|
|||
)
|
||||
|
||||
if db:
|
||||
_process_handler(db)
|
||||
await _process_handler(db)
|
||||
else:
|
||||
with SessionLocal() as db_session:
|
||||
_process_handler(db_session)
|
||||
await _process_handler(db_session)
|
||||
|
||||
|
||||
@router.post('/', response_model=FileModelResponse)
|
||||
|
|
|
|||
|
|
@ -469,45 +469,78 @@
|
|||
input.directory = true;
|
||||
input.multiple = true;
|
||||
input.style.display = 'none';
|
||||
|
||||
|
||||
document.body.appendChild(input);
|
||||
|
||||
|
||||
// Cancelling the native file picker does not always fire
|
||||
// 'change' or 'error' — especially in Firefox, where the
|
||||
// picker can dismiss without any event, leaving the caller
|
||||
// stuck on "Scanning directory..." forever. Use 'cancel'
|
||||
// (modern browsers) plus a window-focus + delayed sentinel
|
||||
// fallback so the Promise ALWAYS settles: either we got
|
||||
// files, or we resolve with an empty list and the caller's
|
||||
// existing empty-check toasts.
|
||||
let settled = false;
|
||||
const finish = (err?: unknown) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
if (input.parentNode) {
|
||||
input.parentNode.removeChild(input);
|
||||
}
|
||||
window.removeEventListener('focus', onFocus);
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
const onFocus = () => {
|
||||
// 'change' fires after 'focus' returns to the window, so
|
||||
// wait briefly before deciding the user cancelled.
|
||||
setTimeout(() => finish(), 500);
|
||||
};
|
||||
|
||||
input.onchange = async () => {
|
||||
try {
|
||||
const inputFiles = Array.from(input.files || []).filter(
|
||||
(file) => !hasHiddenFolder(file.webkitRelativePath) && !file.name.startsWith('.')
|
||||
);
|
||||
|
||||
|
||||
for (const file of inputFiles) {
|
||||
const relativePath = file.webkitRelativePath || file.name;
|
||||
const fileWithPath = new File([file], relativePath, { type: file.type });
|
||||
|
||||
|
||||
const collectedFile: CollectedFile = {
|
||||
file: fileWithPath,
|
||||
path: relativePath,
|
||||
size: file.size
|
||||
};
|
||||
|
||||
|
||||
if (withHashes) {
|
||||
collectedFile.hash = await calculateFileHash(file);
|
||||
}
|
||||
|
||||
|
||||
files.push(collectedFile);
|
||||
}
|
||||
|
||||
document.body.removeChild(input);
|
||||
resolve();
|
||||
|
||||
finish();
|
||||
} catch (error) {
|
||||
document.body.removeChild(input);
|
||||
reject(error);
|
||||
finish(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
input.onerror = (error) => {
|
||||
document.body.removeChild(input);
|
||||
reject(error);
|
||||
finish(error);
|
||||
};
|
||||
|
||||
|
||||
// Newer browsers fire 'cancel' when the picker is dismissed
|
||||
// without a selection; cast because older lib.dom typings may
|
||||
// not yet declare it.
|
||||
(input as any).oncancel = () => {
|
||||
finish();
|
||||
};
|
||||
|
||||
window.addEventListener('focus', onFocus, { once: true });
|
||||
input.click();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue