-
Notifications
You must be signed in to change notification settings - Fork 15
/
FileLink.java
453 lines (391 loc) · 14.5 KB
/
FileLink.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
package com.filestack;
import com.filestack.errors.InternalException;
import com.filestack.errors.InvalidParameterException;
import com.filestack.errors.PolicySignatureException;
import com.filestack.errors.ResourceNotFoundException;
import com.filestack.errors.ValidationException;
import com.filestack.responses.ImageTagResponse;
import com.filestack.transforms.AvTransform;
import com.filestack.transforms.ImageTransform;
import com.filestack.transforms.ImageTransformTask;
import com.filestack.transforms.tasks.AvTransformOptions;
import com.filestack.util.FsService;
import com.filestack.util.Util;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.reactivex.Completable;
import io.reactivex.Single;
import io.reactivex.functions.Action;
import io.reactivex.schedulers.Schedulers;
import java.io.File;
import java.io.IOException;
import java.net.URLConnection;
import java.util.Map;
import java.util.concurrent.Callable;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
import retrofit2.Response;
/** References and performs operations on an individual file. */
public class FileLink {
private String apiKey;
private String handle;
private Security security;
private FsService fsService;
/**
* Constructs an instance without security.
*
* @see #FileLink(String, String, Security)
*/
public FileLink(String apiKey, String handle) {
this(apiKey, handle, null);
}
/**
* Constructs an instance with security.
*
* @param apiKey account key from the dev portal
* @param handle id for a file, first path segment in dev portal urls
* @param security needs required permissions for your intended actions
*/
public FileLink(String apiKey, String handle, Security security) {
this.apiKey = apiKey;
this.handle = handle;
this.security = security;
this.fsService = new FsService();
}
FileLink() {}
/**
* Builds new {@link FilestackClient}.
*/
public static class Builder {
private String apiKey;
private String handle;
private Security security;
private FsService fsService;
public Builder apiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
public Builder handle(String handle) {
this.handle = handle;
return this;
}
public Builder security(Security security) {
this.security = security;
return this;
}
public Builder service(FsService fsService) {
this.fsService = fsService;
return this;
}
/**
* Create the {@link FileLink} using the configured values.
*/
public FileLink build() {
FileLink fileLink = new FileLink();
fileLink.apiKey = apiKey;
fileLink.handle = handle;
fileLink.security = security;
fileLink.fsService = fsService != null ? fsService : new FsService();
return fileLink;
}
}
/**
* Returns the content of a file.
*
* @return byte[] of file content
* @throws IOException if request fails because of network or other IO issue
* @throws PolicySignatureException if security is missing or invalid
* @throws ResourceNotFoundException if handle isn't found
* @throws InvalidParameterException if handle is malformed
* @throws InternalException if unexpected error occurs
*/
public ResponseBody getContent()
throws IOException, PolicySignatureException, ResourceNotFoundException,
InvalidParameterException, InternalException {
String policy = security != null ? security.getPolicy() : null;
String signature = security != null ? security.getSignature() : null;
Response<ResponseBody> response = fsService.get(this.handle, policy, signature).execute();
Util.checkResponseAndThrow(response);
return response.body();
}
/**
* Saves the file using the name it was uploaded with.
*
* @see #download(String, String)
*/
public File download(String directory)
throws ValidationException, IOException, PolicySignatureException,
ResourceNotFoundException, InvalidParameterException, InternalException {
return download(directory, null);
}
/**
* Saves the file overriding the name it was uploaded with.
*
* @param directory location to save the file in
* @param filename local name for the file
* @throws ValidationException if the path (directory/filename) isn't writable
* @throws IOException if request fails because of network or other IO issue
* @throws PolicySignatureException if security is missing or invalid
* @throws ResourceNotFoundException if handle isn't found
* @throws InvalidParameterException if handle is malformed
* @throws InternalException if unexpected error occurs
*/
public File download(String directory, String filename)
throws ValidationException, IOException, PolicySignatureException,
ResourceNotFoundException, InvalidParameterException, InternalException {
String policy = security != null ? security.getPolicy() : null;
String signature = security != null ? security.getSignature() : null;
Response<ResponseBody> response = fsService.get(this.handle, policy, signature).execute();
Util.checkResponseAndThrow(response);
if (filename == null) {
filename = response.headers().get("x-file-name");
}
File file = Util.createWriteFile(directory + "/" + filename);
ResponseBody body = response.body();
if (body == null) {
throw new IOException();
}
BufferedSource source = body.source();
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(source);
sink.close();
return file;
}
/**
* Replace the content of an existing file handle. Requires security to be set.
* Does not update the filename or MIME type.
*
* @param pathname path to the file, can be local or absolute
* @throws ValidationException if security isn't set or the pathname is invalid
* @throws IOException if request fails because of network or other IO issue
* @throws PolicySignatureException if security is missing or invalid
* @throws ResourceNotFoundException if handle isn't found
* @throws InvalidParameterException if handle is malformed
* @throws InternalException if unexpected error occurs
*/
public void overwrite(String pathname)
throws ValidationException, IOException, PolicySignatureException,
ResourceNotFoundException, InvalidParameterException, InternalException {
if (security == null) {
throw new ValidationException("Security must be set in order to overwrite");
}
File file = Util.createReadFile(pathname);
String mimeType = URLConnection.guessContentTypeFromName(file.getName());
RequestBody body = RequestBody.create(MediaType.parse(mimeType), file);
String policy = security.getPolicy();
String signature = security.getSignature();
Response response = fsService.overwrite(handle, policy, signature, body).execute();
Util.checkResponseAndThrow(response);
}
/**
* Deletes a file handle. Requires security to be set.
*
* @throws ValidationException if security isn't set
* @throws IOException if request fails because of network or other IO issue
* @throws PolicySignatureException if security is missing or invalid
* @throws ResourceNotFoundException if handle isn't found
* @throws InvalidParameterException if handle is malformed
* @throws InternalException if unexpected error occurs
*/
public void delete()
throws ValidationException, IOException, PolicySignatureException,
ResourceNotFoundException, InvalidParameterException, InternalException {
if (security == null) {
throw new ValidationException("Security must be set in order to delete");
}
String policy = security.getPolicy();
String signature = security.getSignature();
Response response = fsService.delete(handle, apiKey, policy, signature).execute();
Util.checkResponseAndThrow(response);
}
/**
* Creates an {@link ImageTransform} object for this file.
* A transformation call isn't made directly by this method.
*
* @return {@link ImageTransform ImageTransform} instance configured for this file
*/
public ImageTransform imageTransform() {
return new ImageTransform(this);
}
/**
* Returns tags from the Google Vision API for image FileLinks.
*
* @throws ValidationException if security isn't set
* @throws IOException if request fails because of network or other IO issue
* @throws PolicySignatureException if security is missing or invalid or tagging isn't enabled
* @throws ResourceNotFoundException if handle isn't found
* @throws InvalidParameterException if handle is malformed
* @throws InternalException if unexpected error occurs
*
* @see <a href="https://www.filestack.com/docs/tagging"></a>
*/
public Map<String, Integer> imageTags()
throws ValidationException, IOException, PolicySignatureException,
ResourceNotFoundException, InvalidParameterException, InternalException {
if (security == null) {
throw new ValidationException("Security must be set in order to tag an image");
}
ImageTransform transform = new ImageTransform(this);
transform.addTask(new ImageTransformTask("tags"));
JsonObject json = transform.getContentJson();
Gson gson = new Gson();
ImageTagResponse response = gson.fromJson(json, ImageTagResponse.class);
return response.getAuto();
}
/**
* Determines if an image FileLink is "safe for work" using the Google Vision API.
*
* @throws ValidationException if security isn't set
* @throws IOException if request fails because of network or other IO issue
* @throws PolicySignatureException if security is missing or invalid or tagging isn't enabled
* @throws ResourceNotFoundException if handle isn't found
* @throws InvalidParameterException if handle is malformed
* @throws InternalException if unexpected error occurs
*
* @see <a href="https://www.filestack.com/docs/tagging"></a>
*/
public boolean imageSfw()
throws ValidationException, IOException, PolicySignatureException,
ResourceNotFoundException, InvalidParameterException, InternalException {
if (security == null) {
throw new ValidationException("Security must be set in order to tag an image");
}
ImageTransform transform = new ImageTransform(this);
transform.addTask(new ImageTransformTask("sfw"));
JsonObject json = transform.getContentJson();
return json.get("sfw").getAsBoolean();
}
/**
* Creates an {@link AvTransform} object for this file using default storage options.
*
* @see #avTransform(StorageOptions, AvTransformOptions)
*/
public AvTransform avTransform(AvTransformOptions avOptions) {
return avTransform(null, avOptions);
}
/**
* Creates an {@link AvTransform} object for this file using custom storage options.
* A transformation call isn't made directly by this method.
* For both audio and video transformations.
*
* @param storeOptions options for how to save the file(s) in your storage backend
* @param avOptions options for how ot convert the file
* @return {@link AvTransform ImageTransform} instance configured for this file
*/
public AvTransform avTransform(StorageOptions storeOptions, AvTransformOptions avOptions) {
return new AvTransform(this, storeOptions, avOptions);
}
// Async method wrappers
/**
* Asynchronously returns the content of a file.
*
* @see #getContent()
*/
public Single<ResponseBody> getContentAsync() {
return Single.fromCallable(new Callable<ResponseBody>() {
@Override
public ResponseBody call() throws Exception {
return getContent();
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single());
}
/**
* Asynchronously saves the file using the name it was uploaded with.
*
* @see #download(String, String)
*/
public Single<File> downloadAsync(final String directory) {
return downloadAsync(directory, null);
}
/**
* Asynchronously saves the file overriding the name it was uploaded with.
*
* @see #download(String, String)
*/
public Single<File> downloadAsync(final String directory, final String filename) {
return Single.fromCallable(new Callable<File>() {
@Override
public File call() throws Exception {
return download(directory, filename);
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single());
}
/**
* Asynchronously replace the content of an existing file handle. Requires security to be set.
* Does not update the filename or MIME type.
*
* @see #overwrite(String)
*/
public Completable overwriteAsync(final String pathname) {
return Completable.fromAction(new Action() {
@Override
public void run() throws Exception {
overwrite(pathname);
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single());
}
/**
* Asynchronously deletes a file handle. Requires security to be set.
*
* @see #delete()
*/
public Completable deleteAsync() {
return Completable.fromAction(new Action() {
@Override
public void run() throws Exception {
delete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single());
}
/**
* Asynchronously returns tags from Google Vision API for image FileLinks.
*
* @see #imageTags()
*/
public Single<Map<String, Integer>> imageTagsAsync() {
return Single.fromCallable(new Callable<Map<String, Integer>>() {
@Override
public Map<String, Integer> call() throws Exception {
return imageTags();
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single());
}
/**
* Asynchronously determines if an image FileLink is "safe for work" using the Google Vision API.
*
* @see #imageSfw()
*/
public Single<Boolean> imageSfwAsync() {
return Single.fromCallable(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return imageSfw();
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single());
}
public String getHandle() {
return handle;
}
public Security getSecurity() {
return security;
}
public FsService getFsService() {
return fsService;
}
}