import 'dart:io'; import 'package:jiffy/jiffy.dart'; import 'package:myshelf/models/data.dart'; import 'package:myshelf/models/dtinterval.dart'; import 'package:shelf/shelf.dart'; import 'package:shelf_multipart/shelf_multipart.dart'; import 'package:supabase/supabase.dart'; Future handleFileUpload(Request request) async { final start = Jiffy.now(); // 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 final contentType = request.headers['content-type']; if (contentType == null || !contentType.contains('multipart/form-data')) { return Response(400, body: 'Unsupported content-type'); } // Initialize Supabase client with the bearer token final supabase = SupabaseClient( 'http://baas.fares.cyou:8000', token, ); 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 && name != "" && filename != null) { print("File Uploaded: $filename"); 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 //print("inserting incsvhichupdates"); 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 processCsvData(tempFile, supabase); // 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(" realtime response: $res"); //add filename ta list uploadedFiles.add({ 'filename': filename, 'updated_at': now, }); final end = Jiffy.now(); print( " ${DTInterval(start, end).duration.inSeconds} seconds\n"); // Clean up temporary file await tempFile.delete(); } catch (e) { supabase.dispose(); print("Error processing file:\n $e"); return Response.internalServerError(body: e.toString()); } } } } supabase.dispose(); 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 { supabase.dispose(); return Response(401, body: 'Not a multipart request'); } }