TF-1323 Fix can not attach image on mobile and web

This commit is contained in:
dab246
2023-02-06 10:16:36 +07:00
committed by Dat Vu
parent 10ba3867d8
commit 459b1995a7
16 changed files with 317 additions and 163 deletions
@@ -4,5 +4,5 @@ import 'package:model/upload/file_info.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_attachment.dart';
abstract class AttachmentUploadDataSource {
UploadAttachment uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken});
Future<UploadAttachment> uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken});
}
@@ -5,29 +5,29 @@ import 'package:tmail_ui_user/features/upload/data/datasource/attachment_upload_
import 'package:tmail_ui_user/features/upload/data/network/file_uploader.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_attachment.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
import 'package:uuid/uuid.dart';
class AttachmentUploadDataSourceImpl extends AttachmentUploadDataSource {
final FileUploader _fileUploader;
final Uuid _uuid;
final ExceptionThrower _exceptionThrower;
AttachmentUploadDataSourceImpl(this._fileUploader);
AttachmentUploadDataSourceImpl(this._fileUploader, this._uuid, this._exceptionThrower);
@override
UploadAttachment uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken}) {
final attachmentUploadId = _generateAttachmentUploadId();
final uploadAttachment = UploadAttachment(
attachmentUploadId,
fileInfo,
uploadUri,
_fileUploader,
cancelToken: cancelToken)
..upload();
return uploadAttachment;
}
UploadTaskId _generateAttachmentUploadId() {
return UploadTaskId(const Uuid().v4());
Future<UploadAttachment> uploadAttachment(FileInfo fileInfo, Uri uploadUri, {CancelToken? cancelToken}) {
return Future.sync(() {
return UploadAttachment(
UploadTaskId(_uuid.v4()),
fileInfo,
uploadUri,
_fileUploader,
cancelToken: cancelToken
)..upload();
}).catchError((error) {
_exceptionThrower.throwException(error);
});
}
}
@@ -3,13 +3,18 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:core/core.dart';
import 'package:core/data/network/dio_client.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/build_utils.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:model/email/attachment.dart';
import 'package:model/upload/file_info.dart';
import 'package:model/upload/upload_response.dart';
import 'package:tmail_ui_user/features/upload/data/model/upload_file_arguments.dart';
import 'package:tmail_ui_user/features/upload/domain/exceptions/upload_exception.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
import 'package:tmail_ui_user/features/upload/domain/state/attachment_upload_state.dart';
import 'package:worker_manager/worker_manager.dart' as worker;
@@ -36,21 +41,24 @@ class FileUploader {
uploadUri,
cancelToken: cancelToken);
} else {
final attachmentUploaded = await _isolateExecutor.execute(
arg1: UploadFileArguments(
_dioClient,
uploadId,
fileInfo,
uploadUri,
cancelToken: cancelToken),
fun1: _handleUploadAttachmentAction,
notification: (value) {
if (value is Success) {
log('FileUploader::uploadAttachment(): onUpdateProgress: $value');
onSendController.add(Right(value));
}
});
return attachmentUploaded;
return await _isolateExecutor.execute(
arg1: UploadFileArguments(
_dioClient,
uploadId,
fileInfo,
uploadUri,
cancelToken: cancelToken
),
fun1: _handleUploadAttachmentAction,
notification: (value) {
if (value is Success) {
log('FileUploader::uploadAttachment(): onUpdateProgress: $value');
onSendController.add(Right(value));
}
}
)
.then((value) => value)
.catchError((error) => throw error);
}
}
@@ -58,80 +66,107 @@ class FileUploader {
UploadFileArguments argsUpload,
worker.TypeSendPort sendPort
) async {
try {
final dioClient = argsUpload.dioClient;
final fileInfo = argsUpload.fileInfo;
final uploadUri = argsUpload.uploadUri;
final cancelToken = argsUpload.cancelToken;
final dioClient = argsUpload.dioClient;
final fileInfo = argsUpload.fileInfo;
final uploadUri = argsUpload.uploadUri;
final cancelToken = argsUpload.cancelToken;
final headerParam = dioClient.getHeaders();
headerParam[HttpHeaders.contentTypeHeader] = fileInfo.mimeType;
headerParam[HttpHeaders.contentLengthHeader] = fileInfo.fileSize;
final resultJson = await argsUpload.dioClient.post(
Uri.decodeFull(uploadUri.toString()),
options: Options(headers: headerParam),
data: fileInfo.readStream ?? File(fileInfo.filePath).openRead(),
cancelToken: cancelToken,
onSendProgress: (progress, total) {
log('FileUploader::_handleUploadAttachmentAction():onSendProgress: [${argsUpload.uploadId.id}] = $progress');
sendPort.send(UploadingAttachmentUploadState(
argsUpload.uploadId,
progress,
fileInfo.fileSize));
});
if (cancelToken?.isCancelled == true) {
log('FileUploader::_handleUploadAttachmentAction(): cancelToken');
return null;
final resultJson = await _invokeRequestToServer(
dioClient,
uploadUri,
fileInfo,
cancelToken: cancelToken,
onSendProgress: (count, total) {
log('FileUploader::_handleUploadAttachmentAction():onSendProgress: [${argsUpload.uploadId.id}] = $count');
sendPort.send(
UploadingAttachmentUploadState(
argsUpload.uploadId,
count,
fileInfo.fileSize
)
);
}
final decodeJson = resultJson is Map ? resultJson : jsonDecode(resultJson);
final uploadResponse = UploadResponse.fromJson(decodeJson);
log('FileUploader::_handleUploadAttachmentAction(): ${uploadResponse.toString()}');
return uploadResponse.toAttachment(fileInfo.fileName);
} catch (e) {
log('FileUploader::_handleUploadAttachmentAction(): ERROR: $e');
);
log('FileUploader::_handleUploadAttachmentAction():resultJson: $resultJson');
if (cancelToken?.isCancelled == true) {
log('FileUploader::_handleUploadAttachmentAction(): upload is cancelled');
return null;
}
return _parsingResponse(resultJson: resultJson, fileName: fileInfo.fileName);
}
Future<Attachment?> _handleUploadAttachmentActionOnWeb(
UploadTaskId uploadId,
StreamController<Either<Failure, Success>> onSendController,
FileInfo fileInfo,
Uri uploadUri,
{CancelToken? cancelToken}
UploadTaskId uploadId,
StreamController<Either<Failure, Success>> onSendController,
FileInfo fileInfo,
Uri uploadUri,
{CancelToken? cancelToken}
) async {
try {
final headerParam = _dioClient.getHeaders();
headerParam[HttpHeaders.contentTypeHeader] = fileInfo.mimeType;
headerParam[HttpHeaders.contentLengthHeader] = fileInfo.fileSize;
final resultJson = await _dioClient.post(
Uri.decodeFull(uploadUri.toString()),
options: Options(headers: headerParam),
data: fileInfo.readStream,
cancelToken: cancelToken,
onSendProgress: (progress, total) {
log('FileUploader::_handleUploadAttachmentActionOnWeb():onSendProgress: [$uploadId] = $progress');
onSendController.add(Right(UploadingAttachmentUploadState(
uploadId, progress, fileInfo.fileSize)));
}
);
if (cancelToken?.isCancelled == true) {
log('FileUploader::_handleUploadAttachmentAction(): cancelToken');
return null;
final resultJson = await _invokeRequestToServer(
_dioClient,
uploadUri,
fileInfo,
cancelToken: cancelToken,
onSendProgress: (count, total) {
log('FileUploader::_handleUploadAttachmentActionOnWeb():onSendProgress: [${uploadId.id}] = $count');
onSendController.add(
Right(UploadingAttachmentUploadState(
uploadId,
count,
fileInfo.fileSize
))
);
}
);
log('FileUploader::_handleUploadAttachmentActionOnWeb():resultJson: $resultJson');
if (cancelToken?.isCancelled == true) {
log('FileUploader::_handleUploadAttachmentActionOnWeb(): upload is cancelled');
return null;
}
return _parsingResponse(resultJson: resultJson, fileName: fileInfo.fileName);
}
static Future<dynamic> _invokeRequestToServer(
DioClient dioClient,
Uri uploadUri,
FileInfo fileInfo, {
CancelToken? cancelToken,
ProgressCallback? onSendProgress
}) {
final headerParam = dioClient.getHeaders();
headerParam[HttpHeaders.contentTypeHeader] = fileInfo.mimeType;
headerParam[HttpHeaders.contentLengthHeader] = fileInfo.fileSize;
final data = fileInfo.readStream ?? File(fileInfo.filePath).openRead();
if (cancelToken?.isCancelled == true) {
log('FileUploader::_invokeRequestToServer(): upload is cancelled');
return Future.value();
}
return dioClient.post(
Uri.decodeFull(uploadUri.toString()),
options: Options(headers: headerParam),
data: data,
cancelToken: cancelToken,
onSendProgress: onSendProgress
);
}
static Attachment? _parsingResponse({dynamic resultJson, required String fileName}) {
log('FileUploader::_parsingResponse():resultJson: $resultJson');
if (resultJson != null) {
final decodeJson = resultJson is Map ? resultJson : jsonDecode(resultJson);
final uploadResponse = UploadResponse.fromJson(decodeJson);
log('FileUploader::_handleUploadAttachmentActionOnWeb(): ${uploadResponse.toString()}');
return uploadResponse.toAttachment(fileInfo.fileName);
} catch (e) {
log('FileUploader::_handleUploadAttachmentActionOnWeb(): $e');
return null;
log('FileUploader::_parsingResponse():uploadResponse: ${uploadResponse.toString()}');
return uploadResponse.toAttachment(fileName);
} else {
logError('FileUploader::_parsingResponse(): DataResponseIsNullException');
throw DataResponseIsNullException();
}
}
}