Files
IKAR/lib/backend/ikar_media_session.dart

102 lines
2.8 KiB
Dart

import 'dart:io';
import 'dart:typed_data';
import 'package:kusoft/kusoft.dart' as kb;
import '../core/transport/ikar_network.dart';
/// Media reservations are short-lived URLs on ikar_server.
class IkarMediaSession {
IkarMediaSession(this.baseUri);
final Uri baseUri;
String userAgent() => 'IKAR/1.0.0 Android';
final _client = IkarNetwork.client();
Stream<kb.UploadEvent> _upload(
String url,
Stream<List<int>> bytes,
int size,
String filename,
String contentType,
) async* {
try {
final uri = Uri.parse(url);
if (uri.host != baseUri.host ||
uri.scheme != baseUri.scheme ||
uri.port != baseUri.port)
throw StateError('Адрес загрузки принадлежит другому серверу');
final request = await _client.postUrl(
uri.replace(
queryParameters: {...uri.queryParameters, 'filename': filename},
),
);
request.headers.set('Content-Type', contentType);
request.contentLength = size;
var sent = 0;
await for (final chunk in bytes) {
request.add(chunk);
sent += chunk.length;
yield kb.UploadEvent_Progress(
sent: BigInt.from(sent),
total: BigInt.from(size),
);
}
final response = await request.close().timeout(
const Duration(minutes: 5),
);
final body = await response.fold<List<int>>(
[],
(buffer, chunk) => buffer..addAll(chunk),
);
yield kb.UploadEvent_Done(
status: response.statusCode,
body: Uint8List.fromList(body),
);
} catch (error) {
yield kb.UploadEvent_Error(message: '$error');
}
}
Stream<kb.UploadEvent> uploadFilePath({
required String url,
required String path,
required String filename,
String? contentType,
String? connection,
}) async* {
final file = File(path);
yield* _upload(
url,
file.openRead(),
await file.length(),
filename,
contentType ?? 'application/octet-stream',
);
}
Stream<kb.UploadEvent> uploadPhoto({
required String url,
required Uint8List data,
required String filename,
}) => _upload(url, Stream.value(data), data.length, filename, 'image/jpeg');
Stream<kb.UploadEvent> uploadPhotoPath({
required String url,
required String path,
required String filename,
}) => uploadFilePath(
url: url,
path: path,
filename: filename,
contentType: 'image/jpeg',
);
Stream<kb.UploadEvent> uploadVideoPath({
required String url,
required String path,
required int chunkSize,
required int concurrency,
}) => uploadFilePath(
url: url,
path: path,
filename: 'video.mp4',
contentType: 'video/mp4',
);
void dispose() => _client.close(force: true);
}