tharak-android 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. package/README.md +1 -0
  2. package/build.gradle +45 -0
  3. package/consumer-rules.pro +0 -0
  4. package/libs/vital-sdk.aar +0 -0
  5. package/package.json +22 -0
  6. package/proguard-rules.pro +21 -0
  7. package/src/androidTest/androidTest.iml +11 -0
  8. package/src/androidTest/java/org/tharak/core/ExampleInstrumentedTest.java +27 -0
  9. package/src/androidTest/java/org/thiragatisoft/core/ExampleInstrumentedTest.java +26 -0
  10. package/src/main/AndroidManifest.xml +5 -0
  11. package/src/main/java/org/thiragatisoft/core/AppUtils.java +31 -0
  12. package/src/main/java/org/thiragatisoft/core/FileSelector.java +162 -0
  13. package/src/main/java/org/thiragatisoft/core/MainActivity.java +27 -0
  14. package/src/main/java/org/thiragatisoft/core/RestClient.java +298 -0
  15. package/src/main/java/org/thiragatisoft/core/VitalActivity.java +612 -0
  16. package/src/main/java/org/thiragatisoft/core/VitalsPlugin.java +15 -0
  17. package/src/main/java/org/thiragatisoft/core/VolleyMultipartRequest.java +218 -0
  18. package/src/main/java/org/thiragatisoft/core/http/CapacitorCookieManager.java +175 -0
  19. package/src/main/java/org/thiragatisoft/core/http/CapacitorHttpUrlConnection.java +408 -0
  20. package/src/main/java/org/thiragatisoft/core/http/FilesystemUtils.java +65 -0
  21. package/src/main/java/org/thiragatisoft/core/http/FormUploader.java +219 -0
  22. package/src/main/java/org/thiragatisoft/core/http/Http.java +275 -0
  23. package/src/main/java/org/thiragatisoft/core/http/HttpRequestHandler.java +515 -0
  24. package/src/main/java/org/thiragatisoft/core/http/ICapacitorHttpUrlConnection.java +15 -0
  25. package/src/main/java/org/thiragatisoft/core/http/JSValue.java +68 -0
  26. package/src/main/java/org/thiragatisoft/core/http/MimeType.java +17 -0
  27. package/src/main/main.iml +12 -0
  28. package/src/test/java/org/tharak/ExampleUnitTest.java +17 -0
  29. package/src/test/java/org/tharak/JSObjectTest.java +209 -0
  30. package/src/test/java/org/tharak/PluginMethodHandleTest.java +44 -0
  31. package/src/test/java/org/tharak/util/HostMaskTest.java +70 -0
  32. package/src/test/java/org/thiragatisoft/core/ExampleUnitTest.java +17 -0
  33. package/src/test/test.iml +11 -0
@@ -0,0 +1,408 @@
1
+ package org.thiragatisoft.core.http;
2
+
3
+ import android.os.Build;
4
+ import android.os.LocaleList;
5
+ import android.text.TextUtils;
6
+ import com.getcapacitor.JSArray;
7
+ import com.getcapacitor.JSObject;
8
+ import com.getcapacitor.PluginCall;
9
+ import java.io.DataOutputStream;
10
+ import java.io.IOException;
11
+ import java.io.InputStream;
12
+ import java.net.HttpURLConnection;
13
+ import java.net.ProtocolException;
14
+ import java.net.SocketTimeoutException;
15
+ import java.net.URL;
16
+ import java.net.URLEncoder;
17
+ import java.net.UnknownServiceException;
18
+ import java.nio.charset.StandardCharsets;
19
+ import java.util.Iterator;
20
+ import java.util.List;
21
+ import java.util.Locale;
22
+ import java.util.Map;
23
+ import org.json.JSONException;
24
+ import org.json.JSONObject;
25
+
26
+ public class CapacitorHttpUrlConnection implements ICapacitorHttpUrlConnection {
27
+
28
+ private final HttpURLConnection connection;
29
+
30
+ /**
31
+ * Make a new CapacitorHttpUrlConnection instance, which wraps around HttpUrlConnection
32
+ * and provides some helper functions for setting request headers and the request body
33
+ * @param conn the base HttpUrlConnection. You can pass the value from
34
+ * {@code (HttpUrlConnection) URL.openConnection()}
35
+ */
36
+ public CapacitorHttpUrlConnection(HttpURLConnection conn) {
37
+ connection = conn;
38
+ this.setDefaultRequestProperties();
39
+ }
40
+
41
+ /**
42
+ * Returns the underlying HttpUrlConnection value
43
+ * @return the underlying HttpUrlConnection value
44
+ */
45
+ public HttpURLConnection getHttpConnection() {
46
+ return connection;
47
+ }
48
+
49
+ /**
50
+ * Set the value of the {@code allowUserInteraction} field of
51
+ * this {@code URLConnection}.
52
+ *
53
+ * @param isAllowedInteraction the new value.
54
+ * @throws IllegalStateException if already connected
55
+ */
56
+ public void setAllowUserInteraction(boolean isAllowedInteraction) {
57
+ connection.setAllowUserInteraction(isAllowedInteraction);
58
+ }
59
+
60
+ /**
61
+ * Set the method for the URL request, one of:
62
+ * <UL>
63
+ * <LI>GET
64
+ * <LI>POST
65
+ * <LI>HEAD
66
+ * <LI>OPTIONS
67
+ * <LI>PUT
68
+ * <LI>DELETE
69
+ * <LI>TRACE
70
+ * </UL> are legal, subject to protocol restrictions. The default
71
+ * method is GET.
72
+ *
73
+ * @param method the HTTP method
74
+ * @exception ProtocolException if the method cannot be reset or if
75
+ * the requested method isn't valid for HTTP.
76
+ * @exception SecurityException if a security manager is set and the
77
+ * method is "TRACE", but the "allowHttpTrace"
78
+ * NetPermission is not granted.
79
+ */
80
+ public void setRequestMethod(String method) throws ProtocolException {
81
+ connection.setRequestMethod(method);
82
+ }
83
+
84
+ /**
85
+ * Sets a specified timeout value, in milliseconds, to be used
86
+ * when opening a communications link to the resource referenced
87
+ * by this URLConnection. If the timeout expires before the
88
+ * connection can be established, a
89
+ * java.net.SocketTimeoutException is raised. A timeout of zero is
90
+ * interpreted as an infinite timeout.
91
+ *
92
+ * <p><strong>Warning</strong>: If the hostname resolves to multiple IP
93
+ * addresses, Android's default implementation of {@link HttpURLConnection}
94
+ * will try each in
95
+ * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order. If
96
+ * connecting to each of these addresses fails, multiple timeouts will
97
+ * elapse before the connect attempt throws an exception. Host names
98
+ * that support both IPv6 and IPv4 always have at least 2 IP addresses.
99
+ *
100
+ * @param timeout an {@code int} that specifies the connect
101
+ * timeout value in milliseconds
102
+ * @throws IllegalArgumentException if the timeout parameter is negative
103
+ */
104
+ public void setConnectTimeout(int timeout) {
105
+ if (timeout < 0) {
106
+ throw new IllegalArgumentException("timeout can not be negative");
107
+ }
108
+ connection.setConnectTimeout(timeout);
109
+ }
110
+
111
+ /**
112
+ * Sets the read timeout to a specified timeout, in
113
+ * milliseconds. A non-zero value specifies the timeout when
114
+ * reading from Input stream when a connection is established to a
115
+ * resource. If the timeout expires before there is data available
116
+ * for read, a java.net.SocketTimeoutException is raised. A
117
+ * timeout of zero is interpreted as an infinite timeout.
118
+ *
119
+ * @param timeout an {@code int} that specifies the timeout
120
+ * value to be used in milliseconds
121
+ * @throws IllegalArgumentException if the timeout parameter is negative
122
+ */
123
+ public void setReadTimeout(int timeout) {
124
+ if (timeout < 0) {
125
+ throw new IllegalArgumentException("timeout can not be negative");
126
+ }
127
+ connection.setReadTimeout(timeout);
128
+ }
129
+
130
+ /**
131
+ * Sets whether automatic HTTP redirects should be disabled
132
+ * @param disableRedirects the flag to determine if redirects should be followed
133
+ */
134
+ public void setDisableRedirects(boolean disableRedirects) {
135
+ connection.setInstanceFollowRedirects(!disableRedirects);
136
+ }
137
+
138
+ /**
139
+ * Sets the request headers given a JSObject of key-value pairs
140
+ * @param headers the JSObject values to map to the HttpUrlConnection request headers
141
+ */
142
+ public void setRequestHeaders(JSObject headers) {
143
+ Iterator<String> keys = headers.keys();
144
+ while (keys.hasNext()) {
145
+ String key = keys.next();
146
+ String value = headers.getString(key);
147
+ connection.setRequestProperty(key, value);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Sets the value of the {@code doOutput} field for this
153
+ * {@code URLConnection} to the specified value.
154
+ * <p>
155
+ * A URL connection can be used for input and/or output. Set the DoOutput
156
+ * flag to true if you intend to use the URL connection for output,
157
+ * false if not. The default is false.
158
+ *
159
+ * @param shouldDoOutput the new value.
160
+ * @throws IllegalStateException if already connected
161
+ */
162
+ public void setDoOutput(boolean shouldDoOutput) {
163
+ connection.setDoOutput(shouldDoOutput);
164
+ }
165
+
166
+ /**
167
+ *
168
+ * @param call
169
+ * @throws JSONException
170
+ * @throws IOException
171
+ */
172
+ public void setRequestBody(PluginCall call, JSValue body) throws JSONException, IOException {
173
+ String contentType = connection.getRequestProperty("Content-Type");
174
+ String dataString = "";
175
+
176
+ if (contentType == null || contentType.isEmpty()) return;
177
+
178
+ if (contentType.contains("application/json")) {
179
+ JSArray jsArray = null;
180
+ if (body != null) {
181
+ dataString = body.toString();
182
+ } else {
183
+ jsArray = call.getArray("data", null);
184
+ }
185
+ if (jsArray != null) {
186
+ dataString = jsArray.toString();
187
+ } else if (body == null) {
188
+ dataString = call.getString("data");
189
+ }
190
+ this.writeRequestBody(dataString.toString());
191
+ } else if (contentType.contains("application/x-www-form-urlencoded")) {
192
+ StringBuilder builder = new StringBuilder();
193
+ if(body.getValue() instanceof String){
194
+ builder.append(body.getValue());
195
+ }else {
196
+ JSObject obj = body.toJSObject();
197
+ Iterator<String> keys = obj.keys();
198
+ while (keys.hasNext()) {
199
+ String key = keys.next();
200
+ Object d = obj.get(key);
201
+ builder.append(key).append("=").append(URLEncoder.encode(d.toString(), "UTF-8"));
202
+
203
+ if (keys.hasNext()) {
204
+ builder.append("&");
205
+ }
206
+ }
207
+ }
208
+ this.writeRequestBody(builder.toString());
209
+ } else if (contentType.contains("multipart/form-data")) {
210
+ /*FormUploader uploader = new FormUploader(connection);
211
+
212
+ JSObject obj = body.toJSObject();
213
+ Iterator<String> keys = obj.keys();
214
+ while (keys.hasNext()) {
215
+ String key = keys.next();
216
+ String d = obj.get(key).toString();
217
+ if("file".equals(key)){
218
+ try {
219
+ JSONObject file = new JSONObject(d);
220
+ uploader.addFileBase64Part(key, file.getString("name"), file.getString("base64"));
221
+ }catch (Exception ex){
222
+ //Do Nothing
223
+ }
224
+ }else
225
+ uploader.addFormField(key, d);
226
+ }
227
+ uploader.finish();*/
228
+ JSObject obj = body.toJSObject();
229
+ FormUploader builder = new FormUploader(connection);
230
+ builder.addFileBase64Part("file", obj);
231
+ builder.finish();
232
+ } else {
233
+ this.writeRequestBody(body.toString());
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Writes the provided string to the HTTP connection managed by this instance.
239
+ *
240
+ * @param body The string value to write to the connection stream.
241
+ */
242
+ private void writeRequestBody(String body) throws IOException {
243
+ try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
244
+ os.write(body.getBytes(StandardCharsets.UTF_8));
245
+ os.flush();
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Opens a communications link to the resource referenced by this
251
+ * URL, if such a connection has not already been established.
252
+ * <p>
253
+ * If the {@code connect} method is called when the connection
254
+ * has already been opened (indicated by the {@code connected}
255
+ * field having the value {@code true}), the call is ignored.
256
+ * <p>
257
+ * URLConnection objects go through two phases: first they are
258
+ * created, then they are connected. After being created, and
259
+ * before being connected, various options can be specified
260
+ * (e.g., doInput and UseCaches). After connecting, it is an
261
+ * error to try to set them. Operations that depend on being
262
+ * connected, like getContentLength, will implicitly perform the
263
+ * connection, if necessary.
264
+ *
265
+ * @throws SocketTimeoutException if the timeout expires before
266
+ * the connection can be established
267
+ * @exception IOException if an I/O error occurs while opening the
268
+ * connection.
269
+ */
270
+ public void connect() throws IOException {
271
+ connection.connect();
272
+ }
273
+
274
+ /**
275
+ * Gets the status code from an HTTP response message.
276
+ * For example, in the case of the following status lines:
277
+ * <PRE>
278
+ * HTTP/1.0 200 OK
279
+ * HTTP/1.0 401 Unauthorized
280
+ * </PRE>
281
+ * It will return 200 and 401 respectively.
282
+ * Returns -1 if no code can be discerned
283
+ * from the response (i.e., the response is not valid HTTP).
284
+ * @throws IOException if an error occurred connecting to the server.
285
+ * @return the HTTP Status-Code, or -1
286
+ */
287
+ public int getResponseCode() throws IOException {
288
+ return connection.getResponseCode();
289
+ }
290
+
291
+ /**
292
+ * Returns the value of this {@code URLConnection}'s {@code URL}
293
+ * field.
294
+ *
295
+ * @return the value of this {@code URLConnection}'s {@code URL}
296
+ * field.
297
+ * @see java.net.URLConnection#url
298
+ */
299
+ public URL getURL() {
300
+ return connection.getURL();
301
+ }
302
+
303
+ /**
304
+ * Returns the error stream if the connection failed
305
+ * but the server sent useful data nonetheless. The
306
+ * typical example is when an HTTP server responds
307
+ * with a 404, which will cause a FileNotFoundException
308
+ * to be thrown in connect, but the server sent an HTML
309
+ * help page with suggestions as to what to do.
310
+ *
311
+ * <p>This method will not cause a connection to be initiated. If
312
+ * the connection was not connected, or if the server did not have
313
+ * an error while connecting or if the server had an error but
314
+ * no error data was sent, this method will return null. This is
315
+ * the default.
316
+ *
317
+ * @return an error stream if any, null if there have been no
318
+ * errors, the connection is not connected or the server sent no
319
+ * useful data.
320
+ */
321
+ @Override
322
+ public InputStream getErrorStream() {
323
+ return connection.getErrorStream();
324
+ }
325
+
326
+ /**
327
+ * Returns the value of the named header field.
328
+ * <p>
329
+ * If called on a connection that sets the same header multiple times
330
+ * with possibly different values, only the last value is returned.
331
+ *
332
+ *
333
+ * @param name the name of a header field.
334
+ * @return the value of the named header field, or {@code null}
335
+ * if there is no such field in the header.
336
+ */
337
+ @Override
338
+ public String getHeaderField(String name) {
339
+ return connection.getHeaderField(name);
340
+ }
341
+
342
+ /**
343
+ * Returns an input stream that reads from this open connection.
344
+ *
345
+ * A SocketTimeoutException can be thrown when reading from the
346
+ * returned input stream if the read timeout expires before data
347
+ * is available for read.
348
+ *
349
+ * @return an input stream that reads from this open connection.
350
+ * @exception IOException if an I/O error occurs while
351
+ * creating the input stream.
352
+ * @exception UnknownServiceException if the protocol does not support
353
+ * input.
354
+ * @see #setReadTimeout(int)
355
+ */
356
+ @Override
357
+ public InputStream getInputStream() throws IOException {
358
+ return connection.getInputStream();
359
+ }
360
+
361
+ /**
362
+ * Returns an unmodifiable Map of the header fields.
363
+ * The Map keys are Strings that represent the
364
+ * response-header field names. Each Map value is an
365
+ * unmodifiable List of Strings that represents
366
+ * the corresponding field values.
367
+ *
368
+ * @return a Map of header fields
369
+ */
370
+ public Map<String, List<String>> getHeaderFields() {
371
+ return connection.getHeaderFields();
372
+ }
373
+
374
+ /**
375
+ * Sets the default request properties on the newly created connection.
376
+ * This is called as early as possible to allow overrides by user-provided values.
377
+ */
378
+ private void setDefaultRequestProperties() {
379
+ connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
380
+ String acceptLanguage = buildDefaultAcceptLanguageProperty();
381
+ if (!TextUtils.isEmpty(acceptLanguage)) {
382
+ connection.setRequestProperty("Accept-Language", acceptLanguage);
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Builds and returns a locale string describing the device's current locale preferences.
388
+ */
389
+ private String buildDefaultAcceptLanguageProperty() {
390
+ Locale locale;
391
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
392
+ locale = LocaleList.getDefault().get(0);
393
+ } else {
394
+ locale = Locale.getDefault();
395
+ }
396
+ String result = "";
397
+ String lang = locale.getLanguage();
398
+ String country = locale.getCountry();
399
+ if (!TextUtils.isEmpty(lang)) {
400
+ if (!TextUtils.isEmpty(country)) {
401
+ result = String.format("%s-%s,%s;q=0.5", lang, country, lang);
402
+ } else {
403
+ result = String.format("%s;q=0.5", lang);
404
+ }
405
+ }
406
+ return result;
407
+ }
408
+ }
@@ -0,0 +1,65 @@
1
+ package org.thiragatisoft.core.http;
2
+
3
+ import android.content.Context;
4
+ import android.net.Uri;
5
+ import android.os.Environment;
6
+ import java.io.File;
7
+
8
+ public class FilesystemUtils {
9
+
10
+ public static final String DIRECTORY_DOCUMENTS = "DOCUMENTS";
11
+ public static final String DIRECTORY_APPLICATION = "APPLICATION";
12
+ public static final String DIRECTORY_DOWNLOADS = "DOWNLOADS";
13
+ public static final String DIRECTORY_DATA = "DATA";
14
+ public static final String DIRECTORY_CACHE = "CACHE";
15
+ public static final String DIRECTORY_EXTERNAL = "EXTERNAL";
16
+ public static final String DIRECTORY_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
17
+
18
+ public static File getFileObject(Context c, String path, String directory) {
19
+ if (directory == null || path.startsWith("file://")) {
20
+ Uri u = Uri.parse(path);
21
+ if (u.getScheme() == null || u.getScheme().equals("file")) {
22
+ return new File(u.getPath());
23
+ }
24
+ }
25
+
26
+ File androidDirectory = FilesystemUtils.getDirectory(c, directory);
27
+
28
+ if (androidDirectory == null) {
29
+ return null;
30
+ } else {
31
+ if (!androidDirectory.exists()) {
32
+ androidDirectory.mkdir();
33
+ }
34
+ }
35
+
36
+ return new File(androidDirectory, path);
37
+ }
38
+
39
+ public static File getDirectory(Context c, String directory) {
40
+ switch (directory) {
41
+ case DIRECTORY_APPLICATION:
42
+ case DIRECTORY_DATA:
43
+ return c.getFilesDir();
44
+ case DIRECTORY_DOCUMENTS:
45
+ return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
46
+ case DIRECTORY_DOWNLOADS:
47
+ return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
48
+ case DIRECTORY_CACHE:
49
+ return c.getCacheDir();
50
+ case DIRECTORY_EXTERNAL:
51
+ return c.getExternalFilesDir(null);
52
+ case DIRECTORY_EXTERNAL_STORAGE:
53
+ return Environment.getExternalStorageDirectory();
54
+ }
55
+ return null;
56
+ }
57
+
58
+ /**
59
+ * True if the given directory string is a public storage directory, which is accessible by the user or other apps.
60
+ * @param directory the directory string.
61
+ */
62
+ public static boolean isPublicDirectory(String directory) {
63
+ return (DIRECTORY_DOCUMENTS.equals(directory) || DIRECTORY_DOWNLOADS.equals(directory) || "EXTERNAL_STORAGE".equals(directory));
64
+ }
65
+ }
@@ -0,0 +1,219 @@
1
+ package org.thiragatisoft.core.http;
2
+
3
+ import android.util.Base64;
4
+
5
+ import com.getcapacitor.JSObject;
6
+ import java.io.File;
7
+ import java.io.FileInputStream;
8
+ import java.io.IOException;
9
+ import java.io.OutputStream;
10
+ import java.io.OutputStreamWriter;
11
+ import java.io.PrintWriter;
12
+ import java.net.HttpURLConnection;
13
+ import java.net.URLConnection;
14
+ import java.util.Iterator;
15
+ import java.util.UUID;
16
+ import org.json.JSONException;
17
+ import org.json.JSONObject;
18
+
19
+ public class FormUploader {
20
+
21
+ private final String LINE_FEED = "\r\n";
22
+ private final String boundary;
23
+ private final String charset = "UTF-8";
24
+ private final OutputStream outputStream;
25
+ private final PrintWriter prWriter;
26
+
27
+ /**
28
+ * This constructor initializes a new HTTP POST request with content type
29
+ * is set to multipart/form-data
30
+ * @param connection The HttpUrlConnection to use to upload a Form
31
+ * @throws IOException Thrown if unable to parse the OutputStream of the connection
32
+ */
33
+ public FormUploader(HttpURLConnection connection) throws IOException {
34
+ UUID uuid = UUID.randomUUID();
35
+ boundary = uuid.toString();
36
+
37
+ connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
38
+
39
+ outputStream = connection.getOutputStream();
40
+ prWriter = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
41
+ }
42
+
43
+ /**
44
+ * Adds a form field to the request
45
+ *
46
+ * @param name field name
47
+ * @param value field value
48
+ */
49
+ public void addFormField(String name, String value) {
50
+ prWriter
51
+ .append(LINE_FEED)
52
+ .append("--")
53
+ .append(boundary)
54
+ .append(LINE_FEED)
55
+ .append("Content-Disposition: form-data; name=\"")
56
+ .append(name)
57
+ .append("\"")
58
+ .append(LINE_FEED)
59
+ .append("Content-Type: text/plain; charset=")
60
+ .append(charset)
61
+ .append(LINE_FEED)
62
+ .append(LINE_FEED)
63
+ .append(value)
64
+ .append(LINE_FEED)
65
+ .append("--")
66
+ .append(boundary)
67
+ .append("--")
68
+ .append(LINE_FEED);
69
+ prWriter.flush();
70
+ }
71
+
72
+ /**
73
+ * Adds a form field to the prWriter
74
+ *
75
+ * @param name field name
76
+ * @param value field value
77
+ */
78
+ private void appendFieldToWriter(String name, String value) {
79
+ prWriter
80
+ .append(LINE_FEED)
81
+ .append("--")
82
+ .append(boundary)
83
+ .append(LINE_FEED)
84
+ .append("Content-Disposition: form-data; name=\"")
85
+ .append(name)
86
+ .append("\"")
87
+ .append(LINE_FEED)
88
+ .append("Content-Type: text/plain; charset=")
89
+ .append(charset)
90
+ .append(LINE_FEED)
91
+ .append(LINE_FEED)
92
+ .append(value);
93
+ }
94
+
95
+ /**
96
+ * Adds a upload file section to the request
97
+ *
98
+ * @param fieldName name attribute in <input type="file" name="..." />
99
+ * @param uploadFile a File to be uploaded
100
+ * @throws IOException Thrown if unable to parse the OutputStream of the connection
101
+ */
102
+ public void addFilePart(String fieldName, File uploadFile, JSObject data) throws IOException {
103
+ String fileName = uploadFile.getName();
104
+ prWriter
105
+ .append(LINE_FEED)
106
+ .append("--")
107
+ .append(boundary)
108
+ .append(LINE_FEED)
109
+ .append("Content-Disposition: form-data; name=\"")
110
+ .append(fieldName)
111
+ .append("\"; filename=\"")
112
+ .append(fileName)
113
+ .append("\"")
114
+ .append(LINE_FEED)
115
+ .append("Content-Type: ")
116
+ .append(URLConnection.guessContentTypeFromName(fileName))
117
+ .append(LINE_FEED)
118
+ .append(LINE_FEED);
119
+ prWriter.flush();
120
+
121
+ FileInputStream inputStream = new FileInputStream(uploadFile);
122
+ byte[] buffer = new byte[4096];
123
+ int bytesRead;
124
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
125
+ outputStream.write(buffer, 0, bytesRead);
126
+ }
127
+ outputStream.flush();
128
+ inputStream.close();
129
+
130
+ if (data != null) {
131
+ Iterator<String> keyIterator = data.keys();
132
+ while (keyIterator.hasNext()) {
133
+ String key = keyIterator.next();
134
+ try {
135
+ Object value = data.get(key);
136
+
137
+ if (!(value instanceof String)) continue;
138
+
139
+ appendFieldToWriter(key, value.toString());
140
+ } catch (JSONException e) {
141
+ e.printStackTrace();
142
+ }
143
+ }
144
+ }
145
+
146
+ prWriter.append(LINE_FEED).append("--").append(boundary).append("--").append(LINE_FEED);
147
+ prWriter.flush();
148
+ }
149
+
150
+ /**
151
+ * Adds a header field to the request.
152
+ *
153
+ * @param name - name of the header field
154
+ * @param value - value of the header field
155
+ */
156
+ public void addHeaderField(String name, String value) {
157
+ prWriter.append(name).append(": ").append(value).append(LINE_FEED);
158
+ prWriter.flush();
159
+ }
160
+
161
+ /**
162
+ * Completes the request and receives response from the server.
163
+ * returns a list of Strings as response in case the server returned
164
+ * status OK, otherwise an exception is thrown.
165
+ */
166
+ public void finish() {
167
+ prWriter.append(LINE_FEED);
168
+ prWriter.flush();
169
+ prWriter.append("--").append(boundary).append("--").append(LINE_FEED);
170
+ prWriter.close();
171
+ }
172
+ public void addFileBase64Part(String fieldName, JSONObject data){
173
+ try {
174
+ JSONObject file = new JSONObject(data.getString("file"));
175
+ String fileName = file.getString("name");
176
+ String base64 = file.getString("base64");
177
+ prWriter
178
+ .append(LINE_FEED)
179
+ .append("--")
180
+ .append(boundary)
181
+ .append(LINE_FEED)
182
+ .append("Content-Disposition: form-data; name=\"")
183
+ .append(fieldName)
184
+ .append("\"; filename=\"")
185
+ .append(fileName)
186
+ .append("\"")
187
+ .append(LINE_FEED)
188
+ .append("Content-Type: ")
189
+ .append(URLConnection.guessContentTypeFromName(fileName))
190
+ .append(LINE_FEED)
191
+ .append(LINE_FEED);
192
+ prWriter.flush();
193
+ byte[] buffer = Base64.decode(base64, Base64.DEFAULT);
194
+ outputStream.write(buffer);
195
+ outputStream.flush();
196
+
197
+ if (data != null) {
198
+ Iterator<String> keyIterator = data.keys();
199
+ while (keyIterator.hasNext()) {
200
+ String key = keyIterator.next();
201
+ try {
202
+ Object value = data.get(key);
203
+
204
+ if (!(value instanceof String)) continue;
205
+
206
+ appendFieldToWriter(key, value.toString());
207
+ } catch (JSONException e) {
208
+ e.printStackTrace();
209
+ }
210
+ }
211
+ }
212
+
213
+ prWriter.append(LINE_FEED).append("--").append(boundary).append("--").append(LINE_FEED);
214
+ prWriter.flush();
215
+ }catch (Exception ex){
216
+ ex.printStackTrace();
217
+ }
218
+ }
219
+ }