upload-issue #9
@ -21,8 +21,13 @@ interface UploadResult {
|
|||||||
const UPLOAD_CONFIG = {
|
const UPLOAD_CONFIG = {
|
||||||
maxFileSize: 50 * 1024 * 1024, // 50MB
|
maxFileSize: 50 * 1024 * 1024, // 50MB
|
||||||
allowedTypes: new Set([
|
allowedTypes: new Set([
|
||||||
|
// Images
|
||||||
'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
|
'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
|
||||||
|
|
||||||
|
// Videos
|
||||||
'video/mp4', 'video/webm', 'video/ogg', 'video/avi', 'video/mov',
|
'video/mp4', 'video/webm', 'video/ogg', 'video/avi', 'video/mov',
|
||||||
|
|
||||||
|
// Documents
|
||||||
'application/pdf',
|
'application/pdf',
|
||||||
'application/msword',
|
'application/msword',
|
||||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
@ -30,7 +35,32 @@ const UPLOAD_CONFIG = {
|
|||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
'application/vnd.ms-powerpoint',
|
'application/vnd.ms-powerpoint',
|
||||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
'text/plain', 'text/csv', 'application/json'
|
|
||||||
|
// Text files
|
||||||
|
'text/plain',
|
||||||
|
'text/csv',
|
||||||
|
'text/markdown', // Added markdown
|
||||||
|
'text/x-markdown', // Alternative markdown MIME type
|
||||||
|
'application/json',
|
||||||
|
'application/xml',
|
||||||
|
'text/xml',
|
||||||
|
'text/html',
|
||||||
|
|
||||||
|
// Archives
|
||||||
|
'application/zip',
|
||||||
|
'application/x-tar',
|
||||||
|
'application/gzip',
|
||||||
|
'application/x-gzip',
|
||||||
|
'application/x-zip-compressed',
|
||||||
|
'application/x-rar-compressed',
|
||||||
|
'application/x-7z-compressed',
|
||||||
|
|
||||||
|
// Additional useful formats
|
||||||
|
'application/rtf', // Rich Text Format
|
||||||
|
'text/richtext',
|
||||||
|
'application/x-yaml', // YAML files
|
||||||
|
'text/yaml',
|
||||||
|
'application/yaml'
|
||||||
]),
|
]),
|
||||||
localUploadPath: process.env.LOCAL_UPLOAD_PATH || './public/uploads',
|
localUploadPath: process.env.LOCAL_UPLOAD_PATH || './public/uploads',
|
||||||
publicBaseUrl: process.env.PUBLIC_BASE_URL || 'http://localhost:4321'
|
publicBaseUrl: process.env.PUBLIC_BASE_URL || 'http://localhost:4321'
|
||||||
|
@ -114,8 +114,13 @@ const sortedTools = data.tools.sort((a: any, b: any) => a.name.localeCompare(b.n
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Dokumente, Bilder, Videos (Optional)</label>
|
<label class="form-label">Dokumente, Bilder, Videos (Optional)</label>
|
||||||
<div class="upload-area" id="upload-area">
|
<div class="upload-area" id="upload-area">
|
||||||
<input type="file" id="file-input" multiple accept=".pdf,.doc,.docx,.txt,.md,.zip,.png,.jpg,.jpeg,.gif,.mp4,.webm" class="hidden">
|
<input
|
||||||
<div class="upload-placeholder">
|
type="file"
|
||||||
|
id="file-input"
|
||||||
|
multiple
|
||||||
|
accept=".pdf,.doc,.docx,.txt,.md,.markdown,.csv,.json,.xml,.html,.rtf,.yaml,.yml,.zip,.tar,.gz,.rar,.7z,.png,.jpg,.jpeg,.gif,.webp,.svg,.mp4,.webm,.mov,.avi"
|
||||||
|
class="hidden"
|
||||||
|
> <div class="upload-placeholder">
|
||||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
|
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
|
||||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
||||||
<polyline points="7 10 12 15 17 10"/>
|
<polyline points="7 10 12 15 17 10"/>
|
||||||
@ -342,37 +347,49 @@ class KnowledgebaseForm {
|
|||||||
console.log('[UPLOAD] Response status:', response.status);
|
console.log('[UPLOAD] Response status:', response.status);
|
||||||
console.log('[UPLOAD] Response headers:', Object.fromEntries(response.headers.entries()));
|
console.log('[UPLOAD] Response headers:', Object.fromEntries(response.headers.entries()));
|
||||||
|
|
||||||
|
// FIXED: Read the response body only once
|
||||||
|
let responseData: any;
|
||||||
|
let responseText: string;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try to read as text first (works for both JSON and plain text)
|
||||||
|
responseText = await response.text();
|
||||||
|
console.log('[UPLOAD] Raw response:', responseText.substring(0, 200));
|
||||||
|
|
||||||
|
// Then try to parse as JSON
|
||||||
|
try {
|
||||||
|
responseData = JSON.parse(responseText);
|
||||||
|
} catch (parseError) {
|
||||||
|
// If JSON parsing fails, treat as plain text
|
||||||
|
responseData = { error: responseText };
|
||||||
|
}
|
||||||
|
} catch (readError) {
|
||||||
|
console.error('[UPLOAD] Failed to read response:', readError);
|
||||||
|
throw new Error('Failed to read server response');
|
||||||
|
}
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const result = await response.json();
|
console.log('[UPLOAD] Success result:', responseData);
|
||||||
console.log('[UPLOAD] Success result:', result);
|
|
||||||
|
|
||||||
fileItem.uploaded = true;
|
fileItem.uploaded = true;
|
||||||
fileItem.url = result.url;
|
fileItem.url = responseData.url;
|
||||||
this.renderFileList();
|
this.renderFileList();
|
||||||
|
|
||||||
this.showMessage('success', `Successfully uploaded ${fileItem.name}`);
|
this.showMessage('success', `Successfully uploaded ${fileItem.name}`);
|
||||||
} else {
|
} else {
|
||||||
// Enhanced error handling - read the actual error from response
|
// Enhanced error handling with single response read
|
||||||
let errorMessage = `Upload failed with status ${response.status}`;
|
let errorMessage = `Upload failed with status ${response.status}`;
|
||||||
|
|
||||||
try {
|
if (responseData && responseData.error) {
|
||||||
const errorData = await response.json();
|
errorMessage = responseData.error;
|
||||||
console.error('[UPLOAD] Error response data:', errorData);
|
} else if (responseText) {
|
||||||
|
errorMessage += ` (${responseText.substring(0, 100)})`;
|
||||||
if (errorData.error) {
|
|
||||||
errorMessage = errorData.error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log additional details if available
|
// Log additional details if available
|
||||||
if (errorData.details) {
|
if (responseData && responseData.details) {
|
||||||
console.error('[UPLOAD] Error details:', errorData.details);
|
console.error('[UPLOAD] Error details:', responseData.details);
|
||||||
errorMessage += ` (Details: ${errorData.details.join(', ')})`;
|
errorMessage += ` (Details: ${responseData.details.join(', ')})`;
|
||||||
}
|
|
||||||
} catch (parseError) {
|
|
||||||
console.error('[UPLOAD] Could not parse error response:', parseError);
|
|
||||||
const errorText = await response.text();
|
|
||||||
console.error('[UPLOAD] Raw error response:', errorText);
|
|
||||||
errorMessage += ` (Raw: ${errorText.substring(0, 100)})`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(errorMessage);
|
throw new Error(errorMessage);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user