import 'dart:convert'; import 'dart:io'; import 'package:myshelf/models/data.dart'; import 'package:shelf/shelf.dart'; import 'package:shelf_multipart/shelf_multipart.dart'; import 'package:supabase/supabase.dart'; import 'package:archive/archive.dart'; Future handleFileUpload(Request request) async { // Check authorization final authHeader = request.headers['authorization']; if (authHeader == null || !authHeader.startsWith('Bearer ')) { return Response.forbidden('Authorization header missing or invalid'); } final token = authHeader.substring(7); // Remove 'Bearer ' prefix // Initialize Supabase client with the bearer token final supabase = SupabaseClient( 'http://baas.fares.cyou:8000', token, ); final contentType = request.headers['content-type']; if (contentType == null || !contentType.contains('multipart/form-data')) { return Response(400, body: 'Unsupported content-type'); } if (request.multipart() case var multipart?) { List> uploadedFiles = []; await for (final part in multipart.parts) { final contentDisposition = part.headers['content-disposition']; if (contentDisposition != null && contentDisposition.contains('filename=')) { final name = RegExp(r'name="([^"]*)"').firstMatch(contentDisposition)?.group(1); final filename = RegExp(r'filename="([^"]*)"') .firstMatch(contentDisposition) ?.group(1); if (name != null && filename != null) { try { // Create temporary file final tempFile = File('uploads/$filename'); await tempFile.create(recursive: true); await part.pipe(tempFile.openWrite()); // Upload to Supabase final bytes = await tempFile.readAsBytes(); await supabase.storage.from('csvhich').uploadBinary( filename, bytes, fileOptions: FileOptions( upsert: true, contentType: part.headers['content-type'], ), ); //insertline in csvhichupdates await supabase.from('csvhichupdates').insert({ 'filename': filename, 'updated_at': DateTime.now().toUtc().toIso8601String(), }); //copy file to csvhich archive final nowdt = DateTime.now().toUtc(); final now = nowdt.toIso8601String(); // final timestamp ='${nowdt.year}${nowdt.month.toString().padLeft(2, '0')}${nowdt.day.toString().padLeft(2, '0')}_${nowdt.hour.toString().padLeft(2, '0')}${nowdt.minute.toString().padLeft(2, '0')}'; final timestamp = nowdt.millisecondsSinceEpoch.toString(); //upload file to storage archive bucket try { final archiveFilename = 'upload/${timestamp}_$filename'; await supabase.storage.from('csvhich_archive').uploadBinary( archiveFilename, bytes, fileOptions: FileOptions( upsert: true, contentType: part.headers['content-type'], ), ); } catch (e) { print('Error uploading to archive: $e'); // Continue execution even if archive upload fails } await processCsvFile(tempFile); // No need to subscribe to channel final channel = supabase.channel('csvhichstorage'); final res = await channel.sendBroadcastMessage( event: "upload", payload: { "filename": filename, "updated_at": now, }, ); print("fileupload: realtime res: $res"); //add filename ta list uploadedFiles.add({ 'filename': filename, 'updated_at': now, }); // Clean up temporary file await tempFile.delete(); } catch (e) { print('Error processing file: $e'); return Response.internalServerError( body: 'Error processing file: ${e.toString()}'); } } } } if (uploadedFiles.isNotEmpty) { return Response.ok( '{"status": "success", "files": ${uploadedFiles.toString()}}', headers: {'Content-Type': 'application/json'}, ); } return Response(400, body: 'No files were uploaded'); } else { return Response(401, body: 'Not a multipart request'); } } class FilesAsData { String? filename; String? updatedAt; String data; FilesAsData({ this.filename, this.updatedAt, required this.data, }); } processCsvFile(File tempfile) async { List csvData = []; final filename = tempfile.path.split('/').last; final bytes = await tempfile.readAsBytes(); // Check if file is a zip archive String? csvcontent; if (filename.toLowerCase().endsWith('.zip')) { final archive = ZipDecoder().decodeBytes(bytes); for (final file in archive) { if (!file.isFile) continue; csvcontent = utf8.decode(file.content as List); csvData.add(FilesAsData(filename: file.name, data: csvcontent)); } } else { // For non-zip files, store in extracted folder csvcontent = utf8.decode(bytes); csvData.add(FilesAsData(filename: filename, data: csvcontent)); } // No need to subscribe to channel print((csv2list(csvData!.first!.data!)) .map((e) => Pnleg.fromList(e)) .toList() .first .toMap() .keys); // print( // (csv2list(csvData!.first!.data!)).map((e) => Acleg.fromList(e)).toList()); //insert csv content to database // List> csvData = []; // if (csvcontent != null) { // List lines = csvcontent.split('\n'); // for (String line in lines) { // List values = line.split(','); // csvData.add(values.map((value) { // String trimmedValue = value // .trim() // .replaceAll(RegExp(r'^"|"$'), '') // .replaceAll(RegExp(r'^ | $'), '') // .trim(); // return trimmedValue.isEmpty ? null : trimmedValue; // }).toList()); // } // print(csvData); // } }