@@ -27,8 +27,19 @@ class Fetch {
27
27
return MediaType .parse (mime ?? 'application/octet-stream' );
28
28
}
29
29
30
- StorageException _handleError (dynamic error, StackTrace stack, Uri ? url) {
30
+ StorageException _handleError (
31
+ dynamic error,
32
+ StackTrace stack,
33
+ Uri ? url,
34
+ FetchOptions ? options,
35
+ ) {
31
36
if (error is http.Response ) {
37
+ if (options? .noResolveJson == true ) {
38
+ return StorageException (
39
+ error.body.isEmpty ? error.reasonPhrase ?? '' : error.body,
40
+ statusCode: '${error .statusCode }' ,
41
+ );
42
+ }
32
43
try {
33
44
final data = json.decode (error.body) as Map <String , dynamic >;
34
45
@@ -79,7 +90,7 @@ class Fetch {
79
90
return _handleResponse (streamedResponse, options);
80
91
}
81
92
82
- Future <dynamic > _handleMultipartRequest (
93
+ Future <dynamic > _handleFileRequest (
83
94
String method,
84
95
String url,
85
96
File file,
@@ -88,7 +99,6 @@ class Fetch {
88
99
int retryAttempts,
89
100
StorageRetryController ? retryController,
90
101
) async {
91
- final headers = options? .headers ?? {};
92
102
final contentType = fileOptions.contentType != null
93
103
? MediaType .parse (fileOptions.contentType! )
94
104
: _parseMediaType (file.path);
@@ -98,31 +108,15 @@ class Fetch {
98
108
filename: file.path,
99
109
contentType: contentType,
100
110
);
101
- final request = http.MultipartRequest (method, Uri .parse (url))
102
- ..headers.addAll (headers)
103
- ..files.add (multipartFile)
104
- ..fields['cacheControl' ] = fileOptions.cacheControl
105
- ..headers['x-upsert' ] = fileOptions.upsert.toString ();
106
-
107
- final http.StreamedResponse streamedResponse;
108
- final r = RetryOptions (maxAttempts: (retryAttempts + 1 ));
109
- var attempts = 0 ;
110
- streamedResponse = await r.retry< http.StreamedResponse > (
111
- () async {
112
- attempts++ ;
113
- _log.finest ('Request: attempt: $attempts $method $url $headers ' );
114
- if (httpClient != null ) {
115
- return httpClient! .send (request);
116
- } else {
117
- return request.send ();
118
- }
119
- },
120
- retryIf: (error) =>
121
- retryController? .cancelled != true &&
122
- (error is ClientException || error is TimeoutException ),
111
+ return _handleMultipartRequest (
112
+ method,
113
+ url,
114
+ multipartFile,
115
+ fileOptions,
116
+ options,
117
+ retryAttempts,
118
+ retryController,
123
119
);
124
-
125
- return _handleResponse (streamedResponse, options);
126
120
}
127
121
128
122
Future <dynamic > _handleBinaryFileRequest (
@@ -134,7 +128,6 @@ class Fetch {
134
128
int retryAttempts,
135
129
StorageRetryController ? retryController,
136
130
) async {
137
- final headers = options? .headers ?? {};
138
131
final contentType = fileOptions.contentType != null
139
132
? MediaType .parse (fileOptions.contentType! )
140
133
: _parseMediaType (url);
@@ -145,11 +138,38 @@ class Fetch {
145
138
filename: '' ,
146
139
contentType: contentType,
147
140
);
141
+ return _handleMultipartRequest (
142
+ method,
143
+ url,
144
+ multipartFile,
145
+ fileOptions,
146
+ options,
147
+ retryAttempts,
148
+ retryController,
149
+ );
150
+ }
151
+
152
+ Future <dynamic > _handleMultipartRequest (
153
+ String method,
154
+ String url,
155
+ MultipartFile multipartFile,
156
+ FileOptions fileOptions,
157
+ FetchOptions ? options,
158
+ int retryAttempts,
159
+ StorageRetryController ? retryController,
160
+ ) async {
161
+ final headers = options? .headers ?? {};
148
162
final request = http.MultipartRequest (method, Uri .parse (url))
149
163
..headers.addAll (headers)
150
164
..files.add (multipartFile)
151
165
..fields['cacheControl' ] = fileOptions.cacheControl
152
166
..headers['x-upsert' ] = fileOptions.upsert.toString ();
167
+ if (fileOptions.metadata != null ) {
168
+ request.fields['metadata' ] = json.encode (fileOptions.metadata);
169
+ }
170
+ if (fileOptions.headers != null ) {
171
+ request.headers.addAll (fileOptions.headers! );
172
+ }
153
173
154
174
final http.StreamedResponse streamedResponse;
155
175
final r = RetryOptions (maxAttempts: (retryAttempts + 1 ));
@@ -185,10 +205,24 @@ class Fetch {
185
205
return jsonBody;
186
206
}
187
207
} else {
188
- throw _handleError (response, StackTrace .current, response.request? .url);
208
+ throw _handleError (
209
+ response,
210
+ StackTrace .current,
211
+ response.request? .url,
212
+ options,
213
+ );
189
214
}
190
215
}
191
216
217
+ Future <dynamic > head (String url, {FetchOptions ? options}) async {
218
+ return _handleRequest (
219
+ 'HEAD' ,
220
+ url,
221
+ null ,
222
+ FetchOptions (headers: options? .headers, noResolveJson: true ),
223
+ );
224
+ }
225
+
192
226
Future <dynamic > get (String url, {FetchOptions ? options}) async {
193
227
return _handleRequest ('GET' , url, null , options);
194
228
}
@@ -225,8 +259,15 @@ class Fetch {
225
259
required int retryAttempts,
226
260
required StorageRetryController ? retryController,
227
261
}) async {
228
- return _handleMultipartRequest ('POST' , url, file, fileOptions, options,
229
- retryAttempts, retryController);
262
+ return _handleFileRequest (
263
+ 'POST' ,
264
+ url,
265
+ file,
266
+ fileOptions,
267
+ options,
268
+ retryAttempts,
269
+ retryController,
270
+ );
230
271
}
231
272
232
273
Future <dynamic > putFile (
@@ -237,7 +278,7 @@ class Fetch {
237
278
required int retryAttempts,
238
279
required StorageRetryController ? retryController,
239
280
}) async {
240
- return _handleMultipartRequest (
281
+ return _handleFileRequest (
241
282
'PUT' ,
242
283
url,
243
284
file,
0 commit comments