uploadService.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import { apiClient } from './apiClient';
  2. import { IndexingConfig } from '../types';
  3. // web/services/uploadService.ts
  4. export const uploadService = {
  5. async uploadFile(file: File, authToken: string): Promise<any> {
  6. const formData = new FormData();
  7. formData.append('file', file);
  8. const response = await apiClient.request('/upload', {
  9. method: 'POST',
  10. body: formData,
  11. });
  12. if (!response.ok) {
  13. const errorData = await response.json();
  14. throw new Error(errorData.message || 'fileUploadFailed');
  15. }
  16. return response.json();
  17. },
  18. async uploadFileWithConfig(file: File, config: IndexingConfig, authToken: string): Promise<any> {
  19. const formData = new FormData();
  20. formData.append('file', file);
  21. formData.append('chunkSize', config.chunkSize.toString());
  22. formData.append('chunkOverlap', config.chunkOverlap.toString());
  23. formData.append('embeddingModelId', config.embeddingModelId);
  24. if (config.mode) {
  25. formData.append('mode', config.mode);
  26. }
  27. if (config.groupIds && config.groupIds.length > 0) {
  28. formData.append('groupIds', JSON.stringify(config.groupIds));
  29. }
  30. const response = await apiClient.request('/upload', {
  31. method: 'POST',
  32. body: formData,
  33. });
  34. if (!response.ok) {
  35. const errorData = await response.json();
  36. throw new Error(errorData.message || 'fileUploadFailed');
  37. }
  38. return response.json();
  39. },
  40. async uploadText(content: string, title: string, config: IndexingConfig, authToken: string): Promise<any> {
  41. const { data } = await apiClient.post('/upload/text', {
  42. content,
  43. title,
  44. chunkSize: config.chunkSize.toString(),
  45. chunkOverlap: config.chunkOverlap.toString(),
  46. embeddingModelId: config.embeddingModelId,
  47. mode: config.mode
  48. });
  49. return data;
  50. },
  51. async recommendMode(file: File): Promise<any> {
  52. if (!file || !file.name) {
  53. return {
  54. recommendedMode: 'fast',
  55. reason: 'invalidFile',
  56. warnings: ['incompleteFileInfo'],
  57. };
  58. }
  59. const ext = file.name.toLowerCase().split('.').pop();
  60. const sizeMB = file.size / (1024 * 1024);
  61. const preciseFormats = ['pdf', 'doc', 'docx', 'ppt', 'pptx'];
  62. const supportedFormats = [...preciseFormats, 'xls', 'xlsx', 'txt', 'md', 'html', 'json', 'csv'];
  63. if (!supportedFormats.includes(ext || '')) {
  64. return {
  65. recommendedMode: 'fast',
  66. reason: `unsupportedFileFormat`,
  67. reasonArgs: [ext],
  68. warnings: ['willUseFastMode'],
  69. };
  70. }
  71. if (!preciseFormats.includes(ext || '')) {
  72. return {
  73. recommendedMode: 'fast',
  74. reason: `formatNoPrecise`,
  75. reasonArgs: [ext],
  76. warnings: ['willUseFastMode'],
  77. };
  78. }
  79. if (sizeMB < 5) {
  80. return {
  81. recommendedMode: 'fast',
  82. reason: 'smallFileFastOk',
  83. estimatedCost: 0,
  84. estimatedTime: sizeMB * 2,
  85. warnings: [],
  86. };
  87. }
  88. if (sizeMB < 50) {
  89. return {
  90. recommendedMode: 'precise',
  91. reason: 'mixedContentPreciseRecommended',
  92. estimatedCost: Math.max(0.01, sizeMB * 0.01),
  93. estimatedTime: sizeMB * 8,
  94. warnings: ['willIncurApiCost'],
  95. };
  96. }
  97. return {
  98. recommendedMode: 'precise',
  99. reason: 'largeFilePreciseRecommended',
  100. estimatedCost: sizeMB * 0.015,
  101. estimatedTime: sizeMB * 12,
  102. warnings: ['longProcessingTime', 'highApiCost', 'considerFileSplitting'],
  103. };
  104. },
  105. };