[HOT-FIX] Download attachment is failed on iOS (#4405)
This commit is contained in:
@@ -277,7 +277,7 @@ class EmailAPI
|
|||||||
return _downloadManager.downloadFile(
|
return _downloadManager.downloadFile(
|
||||||
attachment.getDownloadUrl(baseDownloadUrl, accountId),
|
attachment.getDownloadUrl(baseDownloadUrl, accountId),
|
||||||
getTemporaryDirectory(),
|
getTemporaryDirectory(),
|
||||||
attachment.name ?? '',
|
attachment.generateFileName(),
|
||||||
authentication,
|
authentication,
|
||||||
cancelToken: cancelToken);
|
cancelToken: cancelToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class Attachment with EquatableMixin {
|
|||||||
static const String eventICSSubtype = 'ics';
|
static const String eventICSSubtype = 'ics';
|
||||||
static const String eventCalendarSubtype = 'calendar';
|
static const String eventCalendarSubtype = 'calendar';
|
||||||
static const String applicationRTFType = 'application/rtf';
|
static const String applicationRTFType = 'application/rtf';
|
||||||
|
static const String _defaultName = 'unknown-attachment';
|
||||||
|
|
||||||
final PartId? partId;
|
final PartId? partId;
|
||||||
final Id? blobId;
|
final Id? blobId;
|
||||||
@@ -72,11 +73,17 @@ class Attachment with EquatableMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String generateFileName() {
|
String generateFileName() {
|
||||||
if (name?.isNotEmpty == true) {
|
final rawName = (name?.trim().isNotEmpty == true)
|
||||||
return name!;
|
? name!.trim()
|
||||||
} else {
|
: (blobId != null
|
||||||
return '${blobId?.value}.${type?.subtype}';
|
? (type?.subtype != null
|
||||||
}
|
? '${blobId!.value}.${type!.subtype}'
|
||||||
|
: blobId!.value)
|
||||||
|
: _defaultName);
|
||||||
|
|
||||||
|
final sanitized = rawName.replaceAll(RegExp(r'[\\/:*?"<>|]'), '_').trim();
|
||||||
|
// Fall back if sanitized name has no meaningful content (e.g. '???' → '___')
|
||||||
|
return sanitized.contains(RegExp(r'[^_\s]')) ? sanitized : _defaultName;
|
||||||
}
|
}
|
||||||
|
|
||||||
factory Attachment.fromJson(Map<String, dynamic> json) => _$AttachmentFromJson(json);
|
factory Attachment.fromJson(Map<String, dynamic> json) => _$AttachmentFromJson(json);
|
||||||
|
|||||||
@@ -63,5 +63,122 @@ void main() {
|
|||||||
expect(result, 'http://localhost/download/1/some-blob-id/ti%C3%AAu%20%C4%91%E1%BB%81%20attachment?name=ti%C3%AAu%20%C4%91%E1%BB%81%20attachment&type=application%2Foctet-stream');
|
expect(result, 'http://localhost/download/1/some-blob-id/ti%C3%AAu%20%C4%91%E1%BB%81%20attachment?name=ti%C3%AAu%20%C4%91%E1%BB%81%20attachment&type=application%2Foctet-stream');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('generateFileName:', () {
|
||||||
|
test(
|
||||||
|
'should return name when name is not empty',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: 'document.pdf',
|
||||||
|
type: MediaType.parse('application/pdf'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'document.pdf');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return name is trimmed when name has leading/trailing spaces',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: ' document.pdf ',
|
||||||
|
type: MediaType.parse('application/pdf'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'document.pdf');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return blobId with extension when name is null',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
type: MediaType.parse('image/png'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'some-blob-id.png');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return blobId with extension when name is empty',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: '',
|
||||||
|
type: MediaType.parse('image/png'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'some-blob-id.png');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return blobId with extension when name is only whitespace',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: ' ',
|
||||||
|
type: MediaType.parse('image/jpeg'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'some-blob-id.jpeg');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return blobId without extension when name is null and type is null',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'some-blob-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return default name when both name and blobId are null',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
type: MediaType.parse('image/png'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'unknown-attachment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should sanitize name with question mark character',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: 'doc?.pdf',
|
||||||
|
type: MediaType.parse('application/pdf'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'doc_.pdf');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should sanitize name with forward slash character',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: 'folder/document.pdf',
|
||||||
|
type: MediaType.parse('application/pdf'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'folder_document.pdf');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'should return default name when name consists entirely of illegal characters',
|
||||||
|
() {
|
||||||
|
final attachment = Attachment(
|
||||||
|
blobId: Id('some-blob-id'),
|
||||||
|
name: '???',
|
||||||
|
type: MediaType.parse('application/pdf'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(attachment.generateFileName(), 'unknown-attachment');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user