From 9162d6b56e162355049a787b1bbde68e19b468c0 Mon Sep 17 00:00:00 2001 From: otsmr Date: Fri, 23 May 2025 17:36:59 +0200 Subject: [PATCH] upload via http --- lib/src/providers/api/media_send.dart | 92 +++++++++++++-------------- lib/src/providers/api_provider.dart | 19 ++---- 2 files changed, 48 insertions(+), 63 deletions(-) diff --git a/lib/src/providers/api/media_send.dart b/lib/src/providers/api/media_send.dart index 7dafeb4..b089264 100644 --- a/lib/src/providers/api/media_send.dart +++ b/lib/src/providers/api/media_send.dart @@ -1,4 +1,6 @@ +import 'dart:async'; import 'dart:convert'; +import 'package:http/http.dart' as http; import 'dart:io'; import 'dart:typed_data'; import 'package:cryptography_plus/cryptography_plus.dart'; @@ -125,9 +127,12 @@ Future handleSingleMediaFile( } break; case UploadState.hasUploadToken: - if (!await handleUpload(media, tmpCurrentImageBytes)) { - return; // recoverable error. try again when connected again to the server... + if (!await handleUploadHttp(media, tmpCurrentImageBytes)) { + return; } + // if (!await handleUpload(media, tmpCurrentImageBytes)) { + // return; // recoverable error. try again when connected again to the server... + // } break; case UploadState.isUploaded: if (!await handleNotifyReceiver(media)) { @@ -377,61 +382,50 @@ Future handleGetUploadToken(MediaUpload media) async { return true; } -Future handleUpload( +String uint8ListToHex(List bytes) { + return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(); +} + +Future handleUploadHttp( MediaUpload media, Uint8List? tmpCurrentImageBytes) async { Uint8List bytesToUpload = (tmpCurrentImageBytes != null) ? tmpCurrentImageBytes : await readMediaFile(media, "encrypted"); - int fragmentedTransportSize = 1000000; + String apiUrl = + "http${apiProvider.apiSecure}://${apiProvider.apiHost}/api/upload"; - int offset = 0; - - while (offset < bytesToUpload.length) { - Logger("media_send.dart").fine( - "Uploading media file ${media.mediaUploadId} with offset: $offset"); - - int end; - List? checksum; - if (offset + fragmentedTransportSize < bytesToUpload.length) { - end = offset + fragmentedTransportSize; - } else { - end = bytesToUpload.length; - checksum = media.encryptionData!.sha2Hash; - } - - Result wasSend = await apiProvider.uploadData( - media.uploadTokens!.uploadToken, - Uint8List.fromList(bytesToUpload.sublist(offset, end)), - offset, - checksum, - ); - - if (wasSend.isError) { - if (wasSend.error == ErrorCode.InvalidUpdateToken) { - await twonlyDatabase.mediaUploadsDao.updateMediaUpload( - media.mediaUploadId, - MediaUploadsCompanion( - state: Value(UploadState.isEncrypted), - ), - ); - return true; // this will trigger a new token request - } - Logger("media_send.dart") - .shout("error while uploading media: ${wasSend.error}"); - return false; - } - offset = end; - } - - await twonlyDatabase.mediaUploadsDao.updateMediaUpload( - media.mediaUploadId, - MediaUploadsCompanion( - state: Value(UploadState.isUploaded), - ), + var requestMultipart = http.MultipartRequest( + "POST", + Uri.parse(apiUrl), ); - return true; + requestMultipart.files.add(http.MultipartFile.fromBytes( + "file", + bytesToUpload, + filename: uint8ListToHex(media.uploadTokens!.uploadToken), + )); + + try { + var streamedResponse = await requestMultipart.send(); + + await streamedResponse.stream.drain(); + Logger("media_send.dart").info("Uploaded: ${streamedResponse.statusCode}"); + + if (streamedResponse.statusCode == 200) { + await twonlyDatabase.mediaUploadsDao.updateMediaUpload( + media.mediaUploadId, + MediaUploadsCompanion( + state: Value(UploadState.isUploaded), + ), + ); + return true; + } + return false; + } catch (e) { + Logger("media_send.dart").shout("Exception during upload: $e"); + return false; + } } Future handleNotifyReceiver(MediaUpload media) async { diff --git a/lib/src/providers/api_provider.dart b/lib/src/providers/api_provider.dart index 9c0549a..3bba48d 100644 --- a/lib/src/providers/api_provider.dart +++ b/lib/src/providers/api_provider.dart @@ -39,13 +39,9 @@ final lockConnecting = Mutex(); /// It handles errors and does automatically tries to reconnect on /// errors or network changes. class ApiProvider { - final String apiUrl = (kDebugMode) - ? "ws://10.99.0.140:3030/api/client" - : "wss://api.twonly.eu/api/client"; - // ws://api.twonly.eu/api/client - final String? backupApiUrl = (kDebugMode) - ? "ws://10.99.0.140:3030/api/client" - : "wss://api2.twonly.eu/api/client"; + final String apiHost = (kDebugMode) ? "10.99.0.140:3030" : "api.twonly.eu"; + final String apiSecure = (kDebugMode) ? "" : "s"; + bool isAuthenticated = false; ApiProvider(); @@ -125,18 +121,13 @@ class ApiProvider { isAuthenticated = false; + String apiUrl = "ws$apiSecure://$apiHost/api/client"; + log.fine("Trying to connect to the backend $apiUrl!"); if (await _connectTo(apiUrl)) { await onConnected(); return true; } - if (backupApiUrl != null) { - log.fine("Trying to connect to the backup backend $backupApiUrl!"); - if (await _connectTo(backupApiUrl!)) { - await onConnected(); - return true; - } - } return false; }); }