Browse Source

fix(Android <input />): Support file extensions in file input accept attributes (#357)

The current implementation doesn't support a list of file extensions in the accept attribute (e.g. `<input type="file" accept=".jpg, .png">`) while that is a valid value per the HTML spec. I've updated the implementation to convert any file extensions to mime types before we set the type(s) on the intent to rectify the issue. In addition I've updated the `acceptsImages` and `acceptsVideo` methods to handle file extensions as well.
Ryan Linton 5 years ago
parent
commit
803a3b095b

+ 38
- 5
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java View File

@@ -16,6 +16,7 @@ import android.support.annotation.RequiresApi;
16 16
 import android.support.v4.content.ContextCompat;
17 17
 import android.support.v4.content.FileProvider;
18 18
 import android.util.Log;
19
+import android.webkit.MimeTypeMap;
19 20
 import android.webkit.ValueCallback;
20 21
 import android.webkit.WebChromeClient;
21 22
 import android.widget.Toast;
@@ -248,6 +249,9 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
248 249
     if (acceptTypes.isEmpty()) {
249 250
       _acceptTypes = DEFAULT_MIME_TYPES;
250 251
     }
252
+    if (acceptTypes.matches("\\.\\w+")) {
253
+      _acceptTypes = getMimeTypeFromExtension(acceptTypes.replace(".", ""));
254
+    }
251 255
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
252 256
     intent.addCategory(Intent.CATEGORY_OPENABLE);
253 257
     intent.setType(_acceptTypes);
@@ -264,17 +268,27 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
264 268
   }
265 269
 
266 270
   private Boolean acceptsImages(String types) {
267
-    return types.isEmpty() || types.toLowerCase().contains("image");
271
+    String mimeType = types;
272
+    if (types.matches("\\.\\w+")) {
273
+        mimeType = getMimeTypeFromExtension(types.replace(".", ""));
274
+    }
275
+    return mimeType.isEmpty() || mimeType.toLowerCase().contains("image");
268 276
   }
269 277
   private Boolean acceptsImages(String[] types) {
270
-    return isArrayEmpty(types) || arrayContainsString(types, "image");
278
+    String[] mimeTypes = getAcceptedMimeType(types);
279
+    return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "image");
271 280
   }
272 281
 
273 282
   private Boolean acceptsVideo(String types) {
274
-    return types.isEmpty() || types.toLowerCase().contains("video");
283
+    String mimeType = types;
284
+    if (types.matches("\\.\\w+")) {
285
+        mimeType = getMimeTypeFromExtension(types.replace(".", ""));
286
+    }
287
+    return mimeType.isEmpty() || mimeType.toLowerCase().contains("video");
275 288
   }
276 289
   private Boolean acceptsVideo(String[] types) {
277
-    return isArrayEmpty(types) || arrayContainsString(types, "video");
290
+    String[] mimeTypes = getAcceptedMimeType(types);
291
+    return isArrayEmpty(mimeTypes) || arrayContainsString(mimeTypes, "video");
278 292
   }
279 293
 
280 294
   private Boolean arrayContainsString(String[] array, String pattern){
@@ -290,7 +304,26 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
290 304
     if (isArrayEmpty(types)) {
291 305
         return new String[]{DEFAULT_MIME_TYPES};
292 306
     }
293
-    return types;
307
+    String[] mimeTypes = new String[types.length];
308
+    for (int i = 0; i < types.length; i++) {
309
+        String t = types[i];
310
+        // convert file extensions to mime types
311
+        if (t.matches("\\.\\w+")) {
312
+            String mimeType = getMimeTypeFromExtension(t.replace(".", ""));
313
+            mimeTypes[i] = mimeType;
314
+        } else {
315
+            mimeTypes[i] = t;
316
+        }
317
+    }
318
+    return mimeTypes;
319
+  }
320
+
321
+  private String getMimeTypeFromExtension(String extension) {
322
+    String type = null;
323
+    if (extension != null) {
324
+        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
325
+    }
326
+    return type;
294 327
   }
295 328
 
296 329
   private Uri getOutputUri(String intentType) {