mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-28 05:27:35 +00:00
Merge 6392e33dce into b3591e60b1
This commit is contained in:
commit
02660c5678
2 changed files with 161 additions and 17 deletions
|
|
@ -16,7 +16,7 @@
|
|||
import { onMount, tick, getContext, createEventDispatcher } from 'svelte';
|
||||
|
||||
import { createPicker, getAuthToken } from '$lib/utils/google-drive-picker';
|
||||
import { pickAndDownloadFile } from '$lib/utils/onedrive-file-picker';
|
||||
import { pickAndDownloadFiles } from '$lib/utils/onedrive-file-picker';
|
||||
import { KokoroWorker } from '$lib/workers/KokoroWorker';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
|
@ -2216,17 +2216,47 @@
|
|||
}}
|
||||
uploadOneDriveHandler={async (authorityType) => {
|
||||
try {
|
||||
const fileData = await pickAndDownloadFile(authorityType);
|
||||
if (fileData) {
|
||||
const file = new File([fileData.blob], fileData.name, {
|
||||
type: fileData.blob.type || 'application/octet-stream'
|
||||
});
|
||||
await uploadFileHandler(file);
|
||||
const maxFileCount = $config?.file?.max_count;
|
||||
const filesData = await pickAndDownloadFiles(
|
||||
authorityType,
|
||||
maxFileCount
|
||||
);
|
||||
if (filesData && filesData.length > 0) {
|
||||
if (filesData.length > 1) {
|
||||
toast.success(
|
||||
$i18n.t('Uploading {{count}} files from OneDrive...', {
|
||||
count: filesData.length
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
for (const fileData of filesData) {
|
||||
const file = new File([fileData.blob], fileData.name, {
|
||||
type: fileData.blob.type || 'application/octet-stream'
|
||||
});
|
||||
await uploadFileHandler(file);
|
||||
}
|
||||
} else {
|
||||
console.log('No file was selected from OneDrive');
|
||||
console.log('No files were selected from OneDrive');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('OneDrive Error:', error);
|
||||
// Handle specific max file count error
|
||||
if (error.message?.startsWith('MAX_FILE_COUNT_EXCEEDED:')) {
|
||||
const [, count, max] = error.message.split(':');
|
||||
toast.error(
|
||||
$i18n.t('Selected items contain {{count}} files, but maximum is {{max}}.', {
|
||||
count,
|
||||
max
|
||||
})
|
||||
);
|
||||
} else {
|
||||
toast.error(
|
||||
$i18n.t('OneDrive Error: {{error}}', {
|
||||
error: error.message
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}}
|
||||
{onUpload}
|
||||
|
|
|
|||
|
|
@ -180,6 +180,9 @@ interface PickerParams {
|
|||
search: {
|
||||
enabled: boolean;
|
||||
};
|
||||
selection?: {
|
||||
mode?: 'single' | 'multiple' | 'pick';
|
||||
};
|
||||
typesAndSources: {
|
||||
mode: string;
|
||||
pivots: Record<string, boolean>;
|
||||
|
|
@ -211,12 +214,18 @@ function getPickerParams(): PickerParams {
|
|||
search: {
|
||||
enabled: true
|
||||
},
|
||||
selection: {
|
||||
mode: 'multiple'
|
||||
},
|
||||
typesAndSources: {
|
||||
mode: 'files',
|
||||
mode: 'all',
|
||||
pivots: {
|
||||
oneDrive: true,
|
||||
recent: true,
|
||||
myOrganization: config.getAuthorityType() === 'organizations'
|
||||
shared: true,
|
||||
sharedLibraries: true,
|
||||
myOrganization: config.getAuthorityType() === 'organizations',
|
||||
site: config.getAuthorityType() === 'organizations'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -236,10 +245,66 @@ interface OneDriveFileInfo {
|
|||
driveId: string;
|
||||
};
|
||||
'@sharePoint.endpoint': string;
|
||||
folder?: {
|
||||
childCount?: number;
|
||||
};
|
||||
file?: {
|
||||
mimeType?: string;
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// List all items in a folder recursively
|
||||
async function listFolderContentsRecursive(
|
||||
folderInfo: OneDriveFileInfo,
|
||||
authorityType?: 'personal' | 'organizations',
|
||||
currentPath: string = ''
|
||||
): Promise<OneDriveFileInfo[]> {
|
||||
const accessToken = await getToken(undefined, authorityType);
|
||||
if (!accessToken) {
|
||||
throw new Error('Unable to retrieve OneDrive access token.');
|
||||
}
|
||||
|
||||
const childrenUrl = `${folderInfo['@sharePoint.endpoint']}/drives/${folderInfo.parentReference.driveId}/items/${folderInfo.id}/children`;
|
||||
|
||||
const response = await fetch(childrenUrl, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to list folder contents: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const items: OneDriveFileInfo[] = data.value || [];
|
||||
|
||||
const allFiles: OneDriveFileInfo[] = [];
|
||||
|
||||
// Process all items
|
||||
for (const item of items) {
|
||||
// Inherit the @sharePoint.endpoint from parent folder if not present
|
||||
if (!item['@sharePoint.endpoint']) {
|
||||
item['@sharePoint.endpoint'] = folderInfo['@sharePoint.endpoint'];
|
||||
}
|
||||
|
||||
if (item.folder) {
|
||||
// Recursively get files from subfolder
|
||||
const subPath = currentPath ? `${currentPath}/${item.name}` : item.name;
|
||||
const subfolderFiles = await listFolderContentsRecursive(item, authorityType, subPath);
|
||||
allFiles.push(...subfolderFiles);
|
||||
} else if (item.file) {
|
||||
// It's a file, add it to the list
|
||||
allFiles.push(item);
|
||||
}
|
||||
// Skip items that are neither files nor folders (e.g., packages, OneNote notebooks)
|
||||
}
|
||||
|
||||
return allFiles;
|
||||
}
|
||||
|
||||
// Download file from OneDrive
|
||||
async function downloadOneDriveFile(
|
||||
fileInfo: OneDriveFileInfo,
|
||||
|
|
@ -435,20 +500,69 @@ export async function openOneDrivePicker(
|
|||
});
|
||||
}
|
||||
|
||||
// Pick and download file from OneDrive
|
||||
export async function pickAndDownloadFile(
|
||||
authorityType?: 'personal' | 'organizations'
|
||||
): Promise<{ blob: Blob; name: string } | null> {
|
||||
// Pick and download multiple files from OneDrive (with folder support)
|
||||
export async function pickAndDownloadFiles(
|
||||
authorityType?: 'personal' | 'organizations',
|
||||
maxFileCount?: number
|
||||
): Promise<{ blob: Blob; name: string }[] | null> {
|
||||
const pickerResult = await openOneDrivePicker(authorityType);
|
||||
|
||||
if (!pickerResult || !pickerResult.items || pickerResult.items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const selectedFile = pickerResult.items[0];
|
||||
const blob = await downloadOneDriveFile(selectedFile, authorityType);
|
||||
const allFiles: OneDriveFileInfo[] = [];
|
||||
|
||||
return { blob, name: selectedFile.name };
|
||||
// First, expand folders to get all files
|
||||
for (const item of pickerResult.items) {
|
||||
if (item.folder) {
|
||||
// It's a folder, get all files recursively
|
||||
const folderFiles = await listFolderContentsRecursive(item, authorityType, item.name);
|
||||
allFiles.push(...folderFiles);
|
||||
} else {
|
||||
// It's a file
|
||||
allFiles.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any files were actually found
|
||||
if (allFiles.length === 0) {
|
||||
throw new Error('No files found in the selected items.');
|
||||
}
|
||||
|
||||
// Check if the number of files exceeds the configured maximum
|
||||
if (maxFileCount && allFiles.length > maxFileCount) {
|
||||
throw new Error(
|
||||
`MAX_FILE_COUNT_EXCEEDED:${allFiles.length}:${maxFileCount}`
|
||||
);
|
||||
}
|
||||
|
||||
// Download all files with error handling
|
||||
const downloadPromises = allFiles.map(async (fileInfo) => {
|
||||
const blob = await downloadOneDriveFile(fileInfo, authorityType);
|
||||
return {
|
||||
blob,
|
||||
name: fileInfo.name
|
||||
};
|
||||
});
|
||||
|
||||
const results = await Promise.allSettled(downloadPromises);
|
||||
const successful = results
|
||||
.filter((r): r is PromiseFulfilledResult<{ blob: Blob; name: string }> => r.status === 'fulfilled')
|
||||
.map((r) => r.value);
|
||||
|
||||
const failed = results.filter((r) => r.status === 'rejected');
|
||||
|
||||
if (failed.length > 0) {
|
||||
console.warn(`Failed to download ${failed.length} out of ${allFiles.length} files from OneDrive`);
|
||||
// If all downloads failed, throw error
|
||||
if (successful.length === 0) {
|
||||
throw new Error('Failed to download any files from OneDrive');
|
||||
}
|
||||
// If some succeeded, log warning but continue with successful ones
|
||||
}
|
||||
|
||||
return successful.length > 0 ? successful : null;
|
||||
}
|
||||
|
||||
export { downloadOneDriveFile };
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue