| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- 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<Response> 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<Map<String, dynamic>> 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<FilesAsData> 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<int>);
- 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<List<dynamic>> csvData = [];
- // if (csvcontent != null) {
- // List<String> lines = csvcontent.split('\n');
- // for (String line in lines) {
- // List<String> 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);
- // }
- }
|