upload_handler.dart 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import 'dart:io';
  2. import 'package:myshelf/models/data.dart';
  3. import 'package:shelf/shelf.dart';
  4. import 'package:shelf_multipart/shelf_multipart.dart';
  5. import 'package:supabase/supabase.dart';
  6. Future<Response> handleFileUpload(Request request) async {
  7. // Check authorization
  8. final authHeader = request.headers['authorization'];
  9. if (authHeader == null || !authHeader.startsWith('Bearer ')) {
  10. return Response.forbidden('Authorization header missing or invalid');
  11. }
  12. final token = authHeader.substring(7); // Remove 'Bearer ' prefix
  13. final contentType = request.headers['content-type'];
  14. if (contentType == null || !contentType.contains('multipart/form-data')) {
  15. return Response(400, body: 'Unsupported content-type');
  16. }
  17. // Initialize Supabase client with the bearer token
  18. final supabase = SupabaseClient(
  19. 'http://baas.fares.cyou:8000',
  20. token,
  21. );
  22. if (request.multipart() case var multipart?) {
  23. List<Map<String, dynamic>> uploadedFiles = [];
  24. await for (final part in multipart.parts) {
  25. final contentDisposition = part.headers['content-disposition'];
  26. if (contentDisposition != null &&
  27. contentDisposition.contains('filename=')) {
  28. final name =
  29. RegExp(r'name="([^"]*)"').firstMatch(contentDisposition)?.group(1);
  30. final filename = RegExp(r'filename="([^"]*)"')
  31. .firstMatch(contentDisposition)
  32. ?.group(1);
  33. if (name != null && name != "" && filename != null) {
  34. try {
  35. // Create temporary file
  36. final tempFile = File('uploads/$filename');
  37. await tempFile.create(recursive: true);
  38. await part.pipe(tempFile.openWrite());
  39. // Upload to Supabase
  40. final bytes = await tempFile.readAsBytes();
  41. await supabase.storage.from('csvhich').uploadBinary(
  42. filename,
  43. bytes,
  44. fileOptions: FileOptions(
  45. upsert: true,
  46. contentType: part.headers['content-type'],
  47. ),
  48. );
  49. //insertline in csvhichupdates
  50. print("inserting incsvhichupdates");
  51. await supabase.from('csvhichupdates').insert({
  52. 'filename': filename,
  53. 'updated_at': DateTime.now().toUtc().toIso8601String(),
  54. });
  55. //copy file to csvhich archive
  56. final nowdt = DateTime.now().toUtc();
  57. final now = nowdt.toIso8601String();
  58. // 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')}';
  59. final timestamp = nowdt.millisecondsSinceEpoch.toString();
  60. //upload file to storage archive bucket
  61. try {
  62. final archiveFilename = 'upload/${timestamp}_$filename';
  63. await supabase.storage.from('csvhich_archive').uploadBinary(
  64. archiveFilename,
  65. bytes,
  66. fileOptions: FileOptions(
  67. upsert: true,
  68. contentType: part.headers['content-type'],
  69. ),
  70. );
  71. } catch (e) {
  72. print('Error uploading to archive: $e');
  73. // Continue execution even if archive upload fails
  74. }
  75. await processCsvData(tempFile, supabase);
  76. // No need to subscribe to channel
  77. final channel = supabase.channel('csvhichstorage');
  78. final res = await channel.sendBroadcastMessage(
  79. event: "upload",
  80. payload: {
  81. "filename": filename,
  82. "updated_at": now,
  83. },
  84. );
  85. print("realtime response: $res");
  86. //add filename ta list
  87. uploadedFiles.add({
  88. 'filename': filename,
  89. 'updated_at': now,
  90. });
  91. // Clean up temporary file
  92. await tempFile.delete();
  93. } catch (e) {
  94. supabase.dispose();
  95. print("Error processing file:\n $e");
  96. return Response.internalServerError(body: e.toString());
  97. }
  98. }
  99. }
  100. }
  101. supabase.dispose();
  102. if (uploadedFiles.isNotEmpty) {
  103. return Response.ok(
  104. '{"status": "success", "files": ${uploadedFiles.toString()}}',
  105. headers: {'Content-Type': 'application/json'},
  106. );
  107. }
  108. return Response(400, body: 'No files were uploaded');
  109. } else {
  110. supabase.dispose();
  111. return Response(401, body: 'Not a multipart request');
  112. }
  113. }