Skip to content

Commit c388545

Browse files
authored
feat: Add ParseXFile for cross-platform XFile support (#990)
1 parent 540b127 commit c388545

7 files changed

+175
-60
lines changed

packages/dart/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [6.4.0](https://github.com/parse-community/Parse-SDK-Flutter/compare/dart-6.3.0...dart-6.4.0) (2024-03-30)
2+
3+
### Features
4+
5+
* Add `ParseXFile` for cross-platform `XFile` support ([#990](https://github.com/parse-community/Parse-SDK-Flutter/pull/990))
6+
17
## [6.3.0](https://github.com/parse-community/Parse-SDK-Flutter/compare/dart-6.2.0...dart-6.3.0) (2023-11-11)
28

39
### Features

packages/dart/lib/parse_server_sdk.dart

+5-55
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import 'dart:math';
66
import 'dart:typed_data';
77

88
import 'package:collection/collection.dart';
9+
import 'package:cross_file/cross_file.dart';
910
import 'package:dio/dio.dart';
1011
import 'package:meta/meta.dart';
11-
import 'package:mime_type/mime_type.dart';
12+
import 'package:mime/mime.dart';
1213
import 'package:path/path.dart' as path;
1314
import 'package:sembast/sembast.dart';
1415
import 'package:sembast/sembast_io.dart';
@@ -27,109 +28,58 @@ export 'src/network/parse_dio_client.dart';
2728
export 'src/network/parse_http_client.dart';
2829

2930
part 'src/base/parse_constants.dart';
30-
3131
part 'src/data/parse_core_data.dart';
32-
3332
part 'src/data/parse_subclass_handler.dart';
34-
3533
part 'src/enums/parse_enum_api_rq.dart';
36-
3734
part 'src/network/options.dart';
38-
3935
part 'src/network/parse_client.dart';
40-
4136
part 'src/network/parse_connectivity.dart';
42-
4337
part 'src/network/parse_live_query.dart';
44-
4538
part 'src/network/parse_query.dart';
46-
4739
part 'src/objects/parse_acl.dart';
48-
4940
part 'src/objects/parse_array.dart';
50-
5141
part 'src/objects/parse_base.dart';
52-
5342
part 'src/objects/parse_cloneable.dart';
54-
5543
part 'src/objects/parse_config.dart';
56-
5744
part 'src/objects/parse_error.dart';
58-
45+
part 'src/objects/parse_exception.dart';
5946
part 'src/objects/parse_file.dart';
60-
61-
part 'src/objects/parse_number.dart';
62-
6347
part 'src/objects/parse_file_base.dart';
64-
6548
part 'src/objects/parse_file_web.dart';
66-
6749
part 'src/objects/parse_function.dart';
68-
6950
part 'src/objects/parse_geo_point.dart';
70-
7151
part 'src/objects/parse_installation.dart';
72-
52+
part 'src/objects/parse_number.dart';
7353
part 'src/objects/parse_object.dart';
74-
75-
part 'src/objects/parse_exception.dart';
76-
7754
part 'src/objects/parse_operation/parse_add_operation.dart';
78-
7955
part 'src/objects/parse_operation/parse_add_relation_operation.dart';
80-
8156
part 'src/objects/parse_operation/parse_add_unique_operation.dart';
82-
8357
part 'src/objects/parse_operation/parse_increment_operation.dart';
84-
8558
part 'src/objects/parse_operation/parse_operation.dart';
86-
8759
part 'src/objects/parse_operation/parse_remove_operation.dart';
88-
8960
part 'src/objects/parse_operation/parse_remove_relation_operation.dart';
90-
9161
part 'src/objects/parse_relation.dart';
92-
9362
part 'src/objects/parse_response.dart';
94-
9563
part 'src/objects/parse_save_state_aware_child.dart';
96-
9764
part 'src/objects/parse_session.dart';
98-
9965
part 'src/objects/parse_user.dart';
100-
66+
part 'src/objects/parse_x_file.dart';
10167
part 'src/objects/response/parse_error_response.dart';
102-
10368
part 'src/objects/response/parse_exception_response.dart';
104-
10569
part 'src/objects/response/parse_response_builder.dart';
106-
10770
part 'src/objects/response/parse_response_utils.dart';
108-
10971
part 'src/objects/response/parse_success_no_results.dart';
110-
11172
part 'src/storage/core_store.dart';
112-
11373
part 'src/storage/core_store_memory.dart';
114-
11574
part 'src/storage/core_store_sem_impl.dart';
116-
11775
part 'src/storage/xxtea_codec.dart';
118-
11976
part 'src/utils/parse_date_format.dart';
120-
12177
part 'src/utils/parse_decoder.dart';
122-
12378
part 'src/utils/parse_encoder.dart';
124-
12579
part 'src/utils/parse_live_list.dart';
126-
12780
part 'src/utils/parse_logger.dart';
128-
12981
part 'src/utils/parse_login_helpers.dart';
130-
13182
part 'src/utils/parse_utils.dart';
132-
13383
part 'src/utils/valuable.dart';
13484

13585
class Parse {

packages/dart/lib/src/base/parse_constants.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
part of flutter_parse_sdk;
22

33
// Library
4-
const String keySdkVersion = '6.3.0';
4+
const String keySdkVersion = '6.4.0';
55
const String keyLibraryName = 'Flutter Parse SDK';
66

77
// End Points

packages/dart/lib/src/objects/parse_file.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class ParseFile extends ParseFileBase {
8282

8383
final Map<String, String> headers = <String, String>{
8484
HttpHeaders.contentTypeHeader:
85-
mime(file!.path) ?? 'application/octet-stream',
85+
lookupMimeType(file!.path) ?? 'application/octet-stream',
8686
HttpHeaders.contentLengthHeader: '${file!.lengthSync()}',
8787
};
8888

packages/dart/lib/src/objects/parse_file_web.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ParseWebFile extends ParseFileBase {
6161

6262
final Map<String, String> headers = <String, String>{
6363
HttpHeaders.contentTypeHeader:
64-
mime(url ?? name) ?? 'application/octet-stream',
64+
lookupMimeType(url ?? name) ?? 'application/octet-stream',
6565
};
6666
try {
6767
final String uri = ParseCoreData().serverUrl + _path;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
part of flutter_parse_sdk;
2+
3+
class ParseXFile extends ParseFileBase {
4+
/// Creates a new file base XFile
5+
///
6+
/// {https://docs.parseplatform.org/rest/guide/#files/}
7+
ParseXFile(this.file,
8+
{String? name,
9+
String? url,
10+
bool? debug,
11+
ParseClient? client,
12+
bool? autoSendSessionId})
13+
: super(
14+
name: file != null ? path.basename(file.path) : name!,
15+
url: url,
16+
debug: debug,
17+
client: client,
18+
autoSendSessionId: autoSendSessionId,
19+
);
20+
21+
XFile? file;
22+
CancelToken? _cancelToken;
23+
ProgressCallback? _progressCallback;
24+
25+
Future<ParseXFile> loadStorage() async {
26+
// Web not need load storage.
27+
if (parseIsWeb) {
28+
return this;
29+
}
30+
31+
final XFile possibleFile = XFile('${ParseCoreData().fileDirectory}/$name');
32+
// ignore: avoid_slow_async_io
33+
final bool exists = await File(possibleFile.path).exists();
34+
35+
if (exists) {
36+
file = possibleFile;
37+
} else {
38+
file = null;
39+
}
40+
41+
return this;
42+
}
43+
44+
@override
45+
Future<ParseXFile> download({ProgressCallback? progressCallback}) async {
46+
if (url == null) {
47+
return this;
48+
}
49+
50+
progressCallback ??= _progressCallback;
51+
52+
_cancelToken = CancelToken();
53+
54+
if (parseIsWeb) {
55+
final ParseNetworkByteResponse response = await _client.getBytes(
56+
url!,
57+
onReceiveProgress: progressCallback,
58+
cancelToken: _cancelToken,
59+
);
60+
61+
if (response.bytes != null) {
62+
file = XFile.fromData(response.bytes as Uint8List);
63+
}
64+
} else {
65+
file = XFile('${ParseCoreData().fileDirectory}/$name');
66+
await File(file!.path).create();
67+
68+
final ParseNetworkByteResponse response = await _client.getBytes(
69+
url!,
70+
onReceiveProgress: progressCallback,
71+
cancelToken: _cancelToken,
72+
);
73+
await File(file!.path).writeAsBytes(response.bytes!);
74+
}
75+
76+
return this;
77+
}
78+
79+
/// Uploads a file to Parse Server
80+
@override
81+
Future<ParseResponse> upload({ProgressCallback? progressCallback}) async {
82+
if (saved) {
83+
//Creates a Fake Response to return the correct result
84+
final Map<String, String> response = <String, String>{
85+
'url': url!,
86+
'name': name
87+
};
88+
return handleResponse<ParseXFile>(
89+
this,
90+
ParseNetworkResponse(data: json.encode(response), statusCode: 201),
91+
ParseApiRQ.upload,
92+
_debug,
93+
parseClassName);
94+
}
95+
96+
progressCallback ??= _progressCallback;
97+
98+
_cancelToken = CancelToken();
99+
Map<String, String> headers;
100+
if (parseIsWeb) {
101+
headers = <String, String>{
102+
HttpHeaders.contentTypeHeader: file?.mimeType ??
103+
lookupMimeType(url ?? file?.name ?? name,
104+
headerBytes: await file?.readAsBytes()) ??
105+
'application/octet-stream',
106+
};
107+
} else {
108+
headers = <String, String>{
109+
HttpHeaders.contentTypeHeader: file?.mimeType ??
110+
lookupMimeType(file!.path) ??
111+
'application/octet-stream',
112+
HttpHeaders.contentLengthHeader: '${await file!.length()}',
113+
};
114+
}
115+
116+
try {
117+
final String uri = ParseCoreData().serverUrl + _path;
118+
119+
Stream<List<int>>? data;
120+
if (parseIsWeb) {
121+
data = Stream<List<int>>.fromIterable(
122+
<List<int>>[await file!.readAsBytes()]);
123+
} else {
124+
data = file!.openRead();
125+
}
126+
127+
final ParseNetworkResponse response = await _client.postBytes(
128+
uri,
129+
options: ParseNetworkOptions(headers: headers),
130+
data: data,
131+
onSendProgress: progressCallback,
132+
cancelToken: _cancelToken,
133+
);
134+
if (response.statusCode == 201) {
135+
final Map<String, dynamic> map = json.decode(response.data);
136+
url = map['url'].toString();
137+
name = map['name'].toString();
138+
}
139+
return handleResponse<ParseXFile>(
140+
this, response, ParseApiRQ.upload, _debug, parseClassName);
141+
} on Exception catch (e) {
142+
return handleException(e, ParseApiRQ.upload, _debug, parseClassName);
143+
}
144+
}
145+
146+
/// Cancels the current request (upload or download of file).
147+
@override
148+
void cancel([dynamic reason]) {
149+
_cancelToken?.cancel(reason);
150+
_cancelToken = null;
151+
}
152+
153+
/// Add Progress Callback
154+
@override
155+
void progressCallback(ProgressCallback progressCallback) {
156+
_progressCallback = progressCallback;
157+
}
158+
}

packages/dart/pubspec.yaml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: parse_server_sdk
22
description: The Dart SDK to connect to Parse Server. Build your apps faster with Parse Platform, the complete application stack.
3-
version: 6.3.0
3+
version: 6.4.0
44
homepage: https://parseplatform.org
55
repository: https://github.com/parse-community/Parse-SDK-Flutter
66
issue_tracker: https://github.com/parse-community/Parse-SDK-Flutter/issues
@@ -34,11 +34,12 @@ dependencies:
3434
uuid: ^3.0.7
3535
meta: ^1.8.0
3636
path: ^1.8.2
37-
mime_type: ^1.0.0
37+
mime: ^1.0.4
3838
timezone: ^0.9.2
3939
universal_io: ^2.2.0
4040
xxtea: ^2.1.0
4141
collection: ^1.16.0
42+
cross_file: ^0.3.3+6
4243

4344
dev_dependencies:
4445
lints: ^2.0.1

0 commit comments

Comments
 (0)