Skip to content

Commit bc37094

Browse files
Merge pull request #451 from appwrite/feat-dart-input-file-improvements
2 parents 3931fbb + 9509ea7 commit bc37094

19 files changed

+418
-264
lines changed

composer.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/SDK/Language/Dart.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -421,18 +421,6 @@ public function getFiles()
421421
'template' => 'dart/lib/src/input_file.dart.twig',
422422
'minify' => false,
423423
],
424-
[
425-
'scope' => 'default',
426-
'destination' => 'lib/src/chunked_upload_io.dart',
427-
'template' => 'dart/lib/src/chunked_upload_io.dart.twig',
428-
'minify' => false,
429-
],
430-
[
431-
'scope' => 'default',
432-
'destination' => 'lib/src/chunked_upload_stub.dart',
433-
'template' => 'dart/lib/src/chunked_upload_stub.dart.twig',
434-
'minify' => false,
435-
],
436424
];
437425
}
438426

src/SDK/Language/Flutter.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -277,18 +277,6 @@ public function getFiles()
277277
'template' => 'flutter/lib/src/input_file.dart.twig',
278278
'minify' => false,
279279
],
280-
[
281-
'scope' => 'default',
282-
'destination' => 'lib/src/chunked_upload_io.dart',
283-
'template' => 'flutter/lib/src/chunked_upload_io.dart.twig',
284-
'minify' => false,
285-
],
286-
[
287-
'scope' => 'default',
288-
'destination' => 'lib/src/chunked_upload_stub.dart',
289-
'template' => 'flutter/lib/src/chunked_upload_stub.dart.twig',
290-
'minify' => false,
291-
],
292280
];
293281
}
294282
}

templates/dart/base/requests/file.twig

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,23 @@
99
};
1010

1111
{% if 'multipart/form-data' in method.consumes %}
12-
dynamic res;
13-
if(identical(0, 0.0)) {
12+
String idParamName = '';
1413
{% for parameter in method.parameters.all %}
1514
{% if parameter.type == 'file' %}
16-
params['{{ parameter.name }}'] = {{ parameter.name }}.file;
17-
{% endif %}
18-
{% endfor %}
19-
res = await client.call(HttpMethod.{{ method.method | caseLower }}, path: path, params: params, headers: headers);
20-
} else {
21-
String idParamName = '';
22-
{% for parameter in method.parameters.all %}
23-
{% if parameter.type == 'file' %}
24-
final paramName = '{{ parameter.name }}';
15+
final paramName = '{{ parameter.name }}';
2516
{% endif %}
2617
{% if parameter.isUploadID %}
27-
idParamName = '{{ parameter.name }}';
18+
idParamName = '{{ parameter.name }}';
2819
{% endif %}
2920
{% endfor %}
30-
res = await chunkedUpload(
31-
client: client,
21+
final res = await client.chunkedUpload(
3222
path: path,
3323
params: params,
3424
paramName: paramName,
3525
idParamName: idParamName,
3626
headers: headers,
3727
onProgress: onProgress,
38-
);
39-
}
28+
);
4029

4130
return {% if method.responseModel and method.responseModel != 'any' %}models.{{method.responseModel | caseUcfirst}}.fromMap(res.data){% else %} res.data{% endif %};
4231
{% endif %}

templates/dart/lib/package.dart.twig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@ library {{ language.params.packageName }};
22

33
import 'dart:async';
44
import 'dart:typed_data';
5-
import 'src/chunked_upload_stub.dart'
6-
if (dart.library.io) 'src/chunked_upload_io.dart';
5+
import 'package:http/http.dart' show MultipartFile;
76
import 'src/enums.dart';
87
import 'src/client.dart';
98
import 'src/service.dart';
109
import 'src/input_file.dart';
1110
import 'src/upload_progress.dart';
1211
import 'models.dart' as models;
12+
import 'src/exception.dart';
1313

1414
export 'src/response.dart';
1515
export 'src/client.dart';
1616
export 'src/exception.dart';
1717
export 'src/input_file.dart';
1818
export 'src/upload_progress.dart';
19-
export 'package:http/http.dart' show MultipartFile;
2019

2120
part 'query.dart';
2221
{% for service in spec.services %}

templates/dart/lib/src/chunked_upload_io.dart.twig

Lines changed: 0 additions & 78 deletions
This file was deleted.

templates/dart/lib/src/chunked_upload_stub.dart.twig

Lines changed: 0 additions & 14 deletions
This file was deleted.

templates/dart/lib/src/client.dart.twig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import 'client_stub.dart'
33
if (dart.library.html) 'client_browser.dart'
44
if (dart.library.io) 'client_io.dart';
55
import 'response.dart';
6+
import 'input_file.dart';
7+
import 'upload_progress.dart';
68

79
abstract class Client {
810
static const int CHUNK_SIZE = 5*1024*1024;
@@ -29,6 +31,15 @@ abstract class Client {
2931

3032
Client addHeader(String key, String value);
3133

34+
Future<Response> chunkedUpload({
35+
required String path,
36+
required Map<String, dynamic> params,
37+
required String paramName,
38+
required String idParamName,
39+
required Map<String, String> headers,
40+
Function(UploadProgress)? onProgress,
41+
});
42+
3243
Future<Response> call(HttpMethod method, {
3344
String path = '',
3445
Map<String, String> headers = const {},

templates/dart/lib/src/client_browser.dart.twig

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import 'dart:math';
12
import 'package:http/http.dart' as http;
23
import 'package:http/browser_client.dart';
34
import 'client_mixin.dart';
45
import 'enums.dart';
56
import 'exception.dart';
67
import 'client_base.dart';
78
import 'response.dart';
9+
import 'input_file.dart';
10+
import 'upload_progress.dart';
811

912
ClientBase createClient({
1013
required String endPoint,
@@ -13,6 +16,7 @@ ClientBase createClient({
1316
ClientBrowser(endPoint: endPoint, selfSigned: selfSigned);
1417

1518
class ClientBrowser extends ClientBase with ClientMixin {
19+
static const int CHUNK_SIZE = 5*1024*1024;
1620
String _endPoint;
1721
Map<String, String>? _headers;
1822
@override
@@ -70,6 +74,73 @@ class ClientBrowser extends ClientBase with ClientMixin {
7074
return this;
7175
}
7276

77+
@override
78+
Future<Response> chunkedUpload({
79+
required String path,
80+
required Map<String, dynamic> params,
81+
required String paramName,
82+
required String idParamName,
83+
required Map<String, String> headers,
84+
Function(UploadProgress)? onProgress,
85+
}) async {
86+
InputFile file = params[paramName];
87+
if (file.bytes == null) {
88+
throw {{spec.title | caseUcfirst}}Exception("File bytes must be provided for Flutter web");
89+
}
90+
91+
int size = file.bytes!.length;
92+
93+
late Response res;
94+
if (size <= CHUNK_SIZE) {
95+
params[paramName] = http.MultipartFile.fromBytes(paramName, file.bytes!, filename: file.filename);
96+
return call(
97+
HttpMethod.post,
98+
path: path,
99+
params: params,
100+
headers: headers,
101+
);
102+
}
103+
104+
var offset = 0;
105+
if (idParamName.isNotEmpty && params[idParamName] != 'unique()') {
106+
//make a request to check if a file already exists
107+
try {
108+
res = await call(
109+
HttpMethod.get,
110+
path: path + '/' + params[idParamName],
111+
headers: headers,
112+
);
113+
final int chunksUploaded = res.data['chunksUploaded'] as int;
114+
offset = min(size, chunksUploaded * CHUNK_SIZE);
115+
} on {{spec.title | caseUcfirst}}Exception catch (_) {}
116+
}
117+
118+
while (offset < size) {
119+
var chunk;
120+
final end = min(offset + CHUNK_SIZE-1, size-1);
121+
chunk = file.bytes!.getRange(offset, end).toList();
122+
params[paramName] =
123+
http.MultipartFile.fromBytes(paramName, chunk, filename: file.filename);
124+
headers['content-range'] =
125+
'bytes $offset-${min<int>(((offset + CHUNK_SIZE) - 1), size)}/$size';
126+
res = await call(HttpMethod.post,
127+
path: path, headers: headers, params: params);
128+
offset += CHUNK_SIZE;
129+
if (offset < size) {
130+
headers['x-{{spec.title | caseLower }}-id'] = res.data['\$id'];
131+
}
132+
final progress = UploadProgress(
133+
$id: res.data['\$id'] ?? '',
134+
progress: min(offset - 1, size) / size * 100,
135+
sizeUploaded: min(offset - 1, size),
136+
chunksTotal: res.data['chunksTotal'] ?? 0,
137+
chunksUploaded: res.data['chunksUploaded'] ?? 0,
138+
);
139+
onProgress?.call(progress);
140+
}
141+
return res;
142+
}
143+
73144
@override
74145
Future<Response> call(
75146
HttpMethod method, {

0 commit comments

Comments
 (0)