upload via http

This commit is contained in:
otsmr 2025-05-23 17:36:59 +02:00
parent cedf20500c
commit 9162d6b56e
2 changed files with 48 additions and 63 deletions

View file

@ -1,4 +1,6 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:cryptography_plus/cryptography_plus.dart'; import 'package:cryptography_plus/cryptography_plus.dart';
@ -125,9 +127,12 @@ Future handleSingleMediaFile(
} }
break; break;
case UploadState.hasUploadToken: case UploadState.hasUploadToken:
if (!await handleUpload(media, tmpCurrentImageBytes)) { if (!await handleUploadHttp(media, tmpCurrentImageBytes)) {
return; // recoverable error. try again when connected again to the server... return;
} }
// if (!await handleUpload(media, tmpCurrentImageBytes)) {
// return; // recoverable error. try again when connected again to the server...
// }
break; break;
case UploadState.isUploaded: case UploadState.isUploaded:
if (!await handleNotifyReceiver(media)) { if (!await handleNotifyReceiver(media)) {
@ -377,62 +382,51 @@ Future<bool> handleGetUploadToken(MediaUpload media) async {
return true; return true;
} }
Future<bool> handleUpload( String uint8ListToHex(List<int> bytes) {
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
}
Future<bool> handleUploadHttp(
MediaUpload media, Uint8List? tmpCurrentImageBytes) async { MediaUpload media, Uint8List? tmpCurrentImageBytes) async {
Uint8List bytesToUpload = (tmpCurrentImageBytes != null) Uint8List bytesToUpload = (tmpCurrentImageBytes != null)
? tmpCurrentImageBytes ? tmpCurrentImageBytes
: await readMediaFile(media, "encrypted"); : await readMediaFile(media, "encrypted");
int fragmentedTransportSize = 1000000; String apiUrl =
"http${apiProvider.apiSecure}://${apiProvider.apiHost}/api/upload";
int offset = 0; var requestMultipart = http.MultipartRequest(
"POST",
while (offset < bytesToUpload.length) { Uri.parse(apiUrl),
Logger("media_send.dart").fine(
"Uploading media file ${media.mediaUploadId} with offset: $offset");
int end;
List<int>? 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) { requestMultipart.files.add(http.MultipartFile.fromBytes(
if (wasSend.error == ErrorCode.InvalidUpdateToken) { "file",
await twonlyDatabase.mediaUploadsDao.updateMediaUpload( bytesToUpload,
media.mediaUploadId, filename: uint8ListToHex(media.uploadTokens!.uploadToken),
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;
}
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( await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
media.mediaUploadId, media.mediaUploadId,
MediaUploadsCompanion( MediaUploadsCompanion(
state: Value(UploadState.isUploaded), state: Value(UploadState.isUploaded),
), ),
); );
return true; return true;
} }
return false;
} catch (e) {
Logger("media_send.dart").shout("Exception during upload: $e");
return false;
}
}
Future<bool> handleNotifyReceiver(MediaUpload media) async { Future<bool> handleNotifyReceiver(MediaUpload media) async {
List<int> alreadyNotified = media.alreadyNotified; List<int> alreadyNotified = media.alreadyNotified;

View file

@ -39,13 +39,9 @@ final lockConnecting = Mutex();
/// It handles errors and does automatically tries to reconnect on /// It handles errors and does automatically tries to reconnect on
/// errors or network changes. /// errors or network changes.
class ApiProvider { class ApiProvider {
final String apiUrl = (kDebugMode) final String apiHost = (kDebugMode) ? "10.99.0.140:3030" : "api.twonly.eu";
? "ws://10.99.0.140:3030/api/client" final String apiSecure = (kDebugMode) ? "" : "s";
: "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";
bool isAuthenticated = false; bool isAuthenticated = false;
ApiProvider(); ApiProvider();
@ -125,18 +121,13 @@ class ApiProvider {
isAuthenticated = false; isAuthenticated = false;
String apiUrl = "ws$apiSecure://$apiHost/api/client";
log.fine("Trying to connect to the backend $apiUrl!"); log.fine("Trying to connect to the backend $apiUrl!");
if (await _connectTo(apiUrl)) { if (await _connectTo(apiUrl)) {
await onConnected(); await onConnected();
return true; 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; return false;
}); });
} }