File Upload does not work inside Webview, Flutter
Asked Answered
S

8

10

I have a website and I converted that website into flutter android application using webview_flutter plugin, everything is working fine.

But there is an issue, there is a form on website in which there is a file input in the form. On website everything works fine but when I click on upload file from android application which I created using webview_flutter plugin, the file input dose not works.

When I click on upload file, it dose not open any popup or anything to allow me to select file from my phone and to upload into the form.

This is my main.dart code:

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:custom_splash/custom_splash.dart';
import 'package:connectivity/connectivity.dart';
import 'package:selfcare/nointernet.dart';

void main() {

  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());

}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "Self Care",
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.red,
        ),
        home: Scaffold(body: splash()));
  }
}

class splash extends StatefulWidget {
  @override
  _splashState createState() => _splashState();
}

class _splashState extends State<splash> {
  String result = '';
  var Colorsval = Colors.white;

  @override
  void initState() {
    CheckStatus();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    if (result != null && result == "Connected") {
      return CustomSplash(
        //backGroundColor: Color(0xFFFF9800),
        imagePath: "assets/images/logo.png",

        home: WebViewClass(),
        duration: 10,
        animationEffect: "zoom-in",
      );
    } else if (result != null && result == "NoInternet") {
      return CustomSplash(
        //backGroundColor: Color(0xFFFF9800),
        imagePath: "assets/images/logo.png",

        home: NoInternetPage(),
        duration: 10,
        animationEffect: "zoom-in",
      );
    } else if (result == null) {
      return CustomSplash(
        //backGroundColor: Color(0xFFFF9800),
        imagePath: "assets/images/logo.png",

        home: NoInternetPage(),
        duration: 10,
        animationEffect: "zoom-in",
      );
    } else {
      return CustomSplash(
        //backGroundColor: Color(0xFFFF9800),
        imagePath: "assets/images/logo.png",

        home: NoInternetPage(),
        duration: 10,
        animationEffect: "zoom-in",
      );
    }
  }

  void CheckStatus() {
    Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
      if (result == ConnectivityResult.mobile ||
          result == ConnectivityResult.wifi) {
        ChangeValues("Connected", Colors.green[900]);
      } else {
        ChangeValues("NoInternet", Colors.red[900]);
      }
    });
  }

  void ChangeValues(String resultval, Color colorval) {
    setState(() {
      result = resultval;
      Colorsval = colorval;
    });
  }
}

class WebViewClass extends StatefulWidget {
  WebViewState createState() => WebViewState();
}

class WebViewState extends State<WebViewClass> {
  num position = 1;

  final key = UniqueKey();

  doneLoading(String A) {
    setState(() {
      position = 0;
    });
  }

  startLoading(String A) {
    setState(() {
      position = 1;
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    Permission.mediaLibrary.request();
    Permission.phone.request();
    Permission.photos.request();
    Permission.storage.request();
    Permission.camera.request();
  }
  //Check Internet Code Starts

  //Check Internet Code Ended here
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        //appBar: AppBar(title: Text('Show ProgressBar While Loading Webview')),
        appBar: PreferredSize(
          child: Container(),
          preferredSize: Size.fromHeight(0.0),
        ),
        body: IndexedStack(index: position, children: <Widget>[
          WebView(
            initialUrl: 'http://mywebsite.com',
            javascriptMode: JavascriptMode.unrestricted,
            key: key,
            onPageFinished: doneLoading,
            onPageStarted: startLoading,
            //onWebResourceError: ,
          ),
          Container(
            color: Colors.white,
            child: Center(
                child: CircularProgressIndicator(
              valueColor: new AlwaysStoppedAnimation<Color>(Colors.red),
            )),
          ),
        ]));
  }
}

And this is the flutter webview plugin I used:

dependencies:
  webview_flutter: ^1.0.7

I also used some permissions to get rid of this problem but not solved it, the permissions:

Permission.mediaLibrary.request();
Permission.phone.request();
Permission.photos.request();
Permission.storage.request();
Permission.camera.request();
Solubility answered 25/1, 2021 at 18:9 Comment(10)
pub.dev/packages/flutter_webview_plugin try this plugin... this has helped me to upload images and files as intended at the website end..Odoacer
But that package still doesn't support sound null-safety.Echinoid
How did you find the solution?Cofield
Guys I've used another webview plugin to resolve the issueSolubility
@MuhammadNoman Can you share the link of the plugin, please? I'm facing the same issueMonteiro
Its Dec, 11 2021 I had this same problem and this plugin saved me pub.dev/packages/flutter_webview_pro Just add to pubspeck.yaml and import in your dart files. That's it.....no need to change methods or anythingValenzuela
@Valenzuela Comment solved it for me. Just make sure you don't have both dependencies listedCatalinacatalo
@Valenzuela have you found a way to customize "Take photo" "Photo library" snackbar?Antonelli
@Antonelli I haven't tried that yet. I will look into itValenzuela
checkout https://mcmap.net/q/1166106/-flutter-webview-cannot-upload-file-from-input-field for fixing file upload issue on Android using webviewAlgonkian
M
4

Since webview_flutter 4.0.2 you can easily do it, as support for Android was just added.

In order to achieve this, you'd have to first check if the platform it's running on is Android and then set your custom listener:

if (Platform.isAndroid) { // or: if (webViewController.platform is AndroidWebViewController)
    final myAndroidController = webViewController.platform as AndroidWebViewController;

    myAndroidController.setOnShowFileSelector( (params) async {
        // Control and show your picker
        // and return a list of Uris.

        return []; // Uris
    });
}
Maffei answered 26/1, 2023 at 11:56 Comment(4)
hey luismiguelss! thanks for bringing this up. Do you know of a package that offers both image gallery and files at the same time without any extra overhead?Ballentine
You can use file_picker, although you'll have to manually request permissionsMaffei
can't find in the link an example for implementing it. Could you link one?Antonelli
For requesting permissions, you can use permission_handler and for actually prompting for file selection you can just navigate to the Usage part of the file_picker's readme.Maffei
P
2

webview_flutter plugin has yet to have support for file upload. You can track the currently open ticket related to this issue here. In the meantime, you can use either flutter_inappwebview or flutter_webview_plugin as a workaround.

Panarabism answered 11/11, 2021 at 19:18 Comment(1)
flutter_webview_plugin does not support file download though. have you found a way around this? I am trying to use flutter_inappwebview but running into issues. The app crashes on Android when I try to make an upload.Turney
A
2

// (1) import these two library by webview_flutter latest package

import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';

// (2) import file_picker latest package // (3) now add this function

Future<List<String>> _androidFilePicker(FileSelectorParams params) async {
final result = await FilePicker.platform.pickFiles();

if (result != null && result.files.single.path != null) {
  final file = File(result.files.single.path!);
  return [file.uri.toString()];
}
return [];

} // (4) now add this function and call it in initial state

 void addFileSelectionListener() async {
if (Platform.isAndroid) {
  final androidController =
      widget.controller.platform as AndroidWebViewController;
  await androidController.setOnShowFileSelector(_androidFilePicker);
} 

} // now it will work well

Algebraist answered 16/2 at 5:31 Comment(0)
E
1

I managed to get this working using the webview_flutter_pro plugin. I've posted details about how to get it to work here:

How to open file picker from gallery or camera android in webview_flutter?

Exuviae answered 29/11, 2022 at 19:58 Comment(0)
E
0

I had the exact same issue after that I released my first Flutter Webview App. Hopefully I have managed to resolve this definitely. Try this helpfull link below. you will find both the explanation of the issue and the solution

File Upload using WebView on Android

Entrust answered 26/11, 2023 at 4:44 Comment(1)
I tried the same thing getting the error - updateAcquireFence: Did not find frame. Are you aware of this issue?Lubumbashi
B
0

Try using set custom listener with latest package webview_flutter: ^4.4.2

Here is the example

  import 'package:webview_flutter_android/webview_flutter_android.dart' as webview_flutter_android;

  ...

  @override
  void initState() {
    
    ...
    if (Platform.isAndroid) {
      final myAndroidController = controller.platform as webview_flutter_android.AndroidWebViewController;
      
      myAndroidController.setOnShowFileSelector(_androidFilePicker);
    }

    Future<List<String>> _androidFilePicker(webview_flutter_android.FileSelectorParams params) async {
      FilePickerResult? result = await FilePicker.platform.pickFiles();

      if (result != null) {
        String filePath = result.files.single.path!;
        String fileName = result.files.single.name;

        // Convert the file to base64
        List<int> fileBytes = await File(filePath).readAsBytes();

        //convert filepath into uri
        final filePath1 = (await getCacheDirectory()).uri.resolve(fileName);
        final file = await File.fromUri(filePath1).create(recursive: true);

        //convert file in bytes
        await file.writeAsBytes(fileBytes, flush: true);

        return [file.uri.toString()];
      }

      return [];
    }

Check full example on gist -

https://gist.github.com/akshaysinghhal/9d04c541623938e96b4446f411a46563#file-web_view_page-dart

Bodoni answered 13/12, 2023 at 6:58 Comment(0)
A
0

You can use "flutter_webview_pro" installation "flutter pub add flutter_webview_pro"

import 'package:flutter/material.dart';
import 'package:flutter_webview_pro/webview_flutter.dart';

void main() => runApp(MaterialApp(home: WebViewExample()));

class WebViewExample extends StatefulWidget {
  @override
  _WebViewExampleState createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Website title'),
      ),
      body: WebView(
        initialUrl: 'https://www.your_url.com', 
        javascriptMode: JavascriptMode.unrestricted,
      ),
    );
  }
}
Alps answered 9/3 at 5:39 Comment(0)
Q
0

My Flutter build used to open the file browsing tool is missing some permissions.

I added that permission and then works fine

Quasimodo answered 11/7 at 5:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.