Flutterfire: [firebase_storage] Add Support Web

Created on 10 Feb 2020  ·  25Comments  ·  Source: FirebaseExtended/flutterfire

Describe the bug
On Flutter Web, StorageReference futures never complete, neither with success or exception.

To Reproduce
Repository ready to reproduce the issue: GitHub

Otherwise, steps to reproduce the behavior:

  1. Switch to flutter master channel & enable web support;
  2. Add dart plugin dependencies:
  3. firebase: ^7.0.0
  4. firebase_storage: ^3.1.1
  5. Add some firebase_storage code, e.g.:
 var storageChild = FirebaseStorage.instance
      .ref()
      .child("test.png");

  // Requires 2+ calls in order to log error in browser console.
  // Underlying 'await FirebaseStorage.channel.invokeMethod' never completes.
  storageChild.getDownloadURL();
  storageChild.getDownloadURL();
  1. Run for web & see errors in Chrome console:
errors.dart:147 Uncaught (in promise) Error: MissingPluginException(No implementation found for method StorageReference#getDownloadUrl on channel plugins.flutter.io/firebase_storage)
    at Object.throw_ [as throw] (errors.dart:196)
    at MethodChannel._invokeMethod (platform_channel.dart:154)
    at _invokeMethod.next (<anonymous>)
    at onValue (async_patch.dart:47)
    at _RootZone.runUnary (zone.dart:1381)
    at _FutureListener.thenAwait.handleValue (future_impl.dart:140)
...
html_dart2js.dart:38356 Overflow on channel: plugins.flutter.io/firebase_storage.  Messages on this channel are being discarded in FIFO fashion.  The engine may not be running or you need to adjust the buffer size if of the channel.
error @ html_dart2js.dart:38356
_printDebugString @ natives.dart:22
...

Expected behavior

  • Calls to StorageReference methods should complete with either success or failure.
  • FirebaseStorage JavaScript SDK should be found as implementation for StorageReference methods.
  • Firebase Storage messaging channel should not be overflowing

Additional context
Repository ready to reproduce the issue: GitHub. On Javascript level (using JS's firebase.storage() directly) it works perfectly, as you'll see in repository set-up.

Flutter Doctor

[✓] Flutter (Channel master, v1.15.3-pre.37, on Mac OS X 10.15.3 19D76, locale en-GB) • Flutter version 1.15.3-pre.37 at /Users/morphingcoffee/Applications/flutter • Framework revision 6dc3bfaa98 (2 days ago), 2020-02-07 18:28:02 -0800 • Engine revision 6158f03ef5 • Dart version 2.8.0 (build 2.8.0-dev.8.0 514a8d4c84)

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.2) • Android SDK at /Users/morphingcoffee/Library/Android/sdk • Android NDK location not configured (optional; useful for native profiling support) • Platform android-29, build-tools 29.0.2 • ANDROID_HOME = /Users/morphingcoffee/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405) ✗ Android license status unknown. Try re-installing or updating your Android SDK Manager. See https://developer.android.com/studio/#downloads or visit https://flutter.dev/setup/#android-setup for detailed instructions.

[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 11.3.1, Build version 11C504 • CocoaPods version 1.8.3

[✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 3.5) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin version 43.0.1 • Dart plugin version 191.8593 • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] Connected device (2 available) • Chrome • chrome • web-javascript • Google Chrome 80.0.3987.87 • Web Server • web-server • web-javascript • Flutter Tools

flutter run -d chrome -v available here

crowd web storage enhancement

Most helpful comment

You guys realize, that you are mostly just spamming other watchers who would also like to see this implemented? Just add your 👍 to the issue and be done with it, if you have nothing of value to add

All 25 comments

Relates to #1903

Firebase storage has no support yet for Flutter for web. [1]
So this is kinda expected.

I believe this should be a feature request not a bug and the title should be something like:
"[firebase_storage] Support Web"

[1] https://github.com/FirebaseExtended/flutterfire#available-flutterfire-plugins

Any news on when this would be supported?

I am in desperate need of uploading images from my flutter web app.
Does anyone know of a workaround until we get cloud storage support on flutter web?
Maybe some way to use cloud functions? or if there is another package that will work to get my images to cloud storage?

I am in desperate need of uploading images from my flutter web app.
Does anyone know of a workaround until we get cloud storage support on flutter web?
Maybe some way to use cloud functions? or if there is another package that will work to get my images to cloud storage?

@AirborneEagle see if using firebase plugin meets your needs. With it you will be able to download/upload files to/from Firebase Storage on _Flutter Web_.

@AirborneEagle you can also upload objects use the JSON API as a workaround.

any news

I found solution:
source article

Example:

fire_storage_service.dart

export 'unsupported_storage.dart'
    if (dart.library.html) 'web_storage.dart'
    if (dart.library.io) 'mobile_storage.dart';

mobile_storage.dart

import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/widgets.dart';

class FireStorageService extends ChangeNotifier {
  FireStorageService();

  static Future<dynamic> loadFromStorage(BuildContext context, String image) async {
    return await FirebaseStorage.instance.ref().child(image).getDownloadURL();
  }
}

unsupported_storage.dart

import 'package:flutter/widgets.dart';

class FireStorageService extends ChangeNotifier {
  FireStorageService._();
  FireStorageService();

  static Future<dynamic> loadFromStorage(BuildContext context, String image) {
    throw ("Platform not found");
  }
}

mobile_storage.dart

import 'package:firebase/firebase.dart';
import 'package:flutter/widgets.dart';

class FireStorageService extends ChangeNotifier {
  FireStorageService();

  static Future<dynamic> loadFromStorage(BuildContext context, String image) async {
    var url = await storage().ref(image).getDownloadURL();
    return url;
  }
}

--

Use it like this:

import 'fire_storage_service.dart';

var resultUrl = (await FireStorageService.loadFromStorage(context, "example.jpg")).toString();

I'm also looking for this feature. Please add, thanks!

I need flutter web support for firebase storage.

I also need this feature. Hype for it.

Please implement this feature!

You guys realize, that you are mostly just spamming other watchers who would also like to see this implemented? Just add your 👍 to the issue and be done with it, if you have nothing of value to add

Hello developers when can we expect web support for Firebase storage on flutter , any tentative month ?
I am currently facing a lot of difficulties in uploading pdf/doc files to firebase storage , I'd be really obliged if one could help me do the same as most picker plugins use dart:io which is not supported by web and dart:html is becoming really messy but is the only way out

@mrityagi We were able to get something decent working using dart:html's FileUploadInputElement and package:firebase 7.3.0 (Firebase JS API Wrapper)

I haven't noticed any issues using it with other firebase packages like firebase_auth.

Hello developers when can we expect web support for Firebase storage on flutter , any tentative month ?
I am currently facing a lot of difficulties in uploading pdf/doc files to firebase storage ,

@dvdmmc Thanks for the direction , i have implemented it and it works fine . I have now uploaded the pdf by writing this piece of code . This is the piece of code on Flutter web which i have used to pick a file on my machine using File_picker web implementation .
FilePickerResult result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'pdf', 'doc'],
withData: true);
if (result != null) {
file = result.files.first;
}
filebyte = file.bytes;

  setState(() {
    imagefile= html.File(filebyte, 'fileName.pdf');
  });

I have now uploaded imagefile to storage
But on firebase storage it's showing the mime type as aplication/octet-stream.
And now when i download it the pdf seems to be corrupted .
I do know that now we need to convert it but not sure if i have even used the right way to upload it , if the upload way is right then how should i convert the file .

@dvdmmc Thanks for the direction , i have implemented it and it works fine . I have now uploaded the pdf by writing this piece of code . This is the piece of code on Flutter web which i have used to pick a file on my machine using File_picker web implementation .
FilePickerResult result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'pdf', 'doc'],
withData: true);
if (result != null) {
file = result.files.first;
}
filebyte = file.bytes;

  setState(() {
    imagefile= html.File(filebyte, 'fileName.pdf');
  });

I have now uploaded imagefile to storage
But on firebase storage it's showing the mime type as aplication/octet-stream.
And now when i download it the pdf seems to be corrupted .
I do know that now we need to convert it but not sure if i have even used the right way to upload it , if the upload way is right then how should i convert the file .

you have to add the meta information with the filetype i guess

Just an FYI this is being actively worked on alongside the rework. There is a PR for the dev release at the moment which federates the plugin with a reworked API.

@Ehesp I've tried that one, 5.0.0-dev.1, but I believe right now is still just for Android, iOS and MacOS, right?

Tried to use it for web, but it didn't worked. But pretty sure this rework is a big step forward and it will soon also be supported
Or did I missed anything?

I'm really in need of this package, using googleapis package for Web and not been able to use it in other platforms greatly restrict possibilities. As soon as it have Web support I will be testing/using it.

It's not there yet, it's being worked on alongside that PR. The rework opens up the possibility for it to be supported on web though.

@mrityagi No problem :-)

For the mime type issue, I use the 'mime_type' package and do something like this:

fb.UploadTask task = ref.put( reader.result, fb.UploadMetadata(contentType: mime(file.name)));

mime is the function in the mime_type package that returns the mime type of the given file.
fb is my alias for the Firebase JS wrapper package.

@dvdmmc Thanks for the direction , i have implemented it and it works fine . I have now uploaded the pdf by writing this piece of code . This is the piece of code on Flutter web which i have used to pick a file on my machine using File_picker web implementation .
FilePickerResult result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'pdf', 'doc'],
withData: true);
if (result != null) {
file = result.files.first;
}
filebyte = file.bytes;

  setState(() {
    imagefile= html.File(filebyte, 'fileName.pdf');
  });

I have now uploaded imagefile to storage
But on firebase storage it's showing the mime type as aplication/octet-stream.
And now when i download it the pdf seems to be corrupted .
I do know that now we need to convert it but not sure if i have even used the right way to upload it , if the upload way is right then how should i convert the file .

@dvdmmc thnx for the info , btw any idea about how I should convert an octetstream/application file to get a PDF file

@mrityagi Sure, happy to help. As long as you set the mime-type correctly, cloud storage should recognise it as a pdf, there isn't anything else you'd need to do.

This worked for me to upload the image to Firebase Storage:
Using image_picker_web: ^1.0.9 packaged to pick up the image from the device.

This for picking up the image:
MediaInfo pickedImage = await ImagePickerWeb.getImageInfo;

Customized method for uploading the image and get the URL of the image.
Below fb is import 'package:firebase/firebase.dart' as fb;
and package version is firebase: ^7.3.0

Future<Uri> uploadFile(
      MediaInfo mediaInfo, String ref, String fileName) async {
    try {
      String mimeType = mime(Path.basename(mediaInfo.fileName));

      final String extension = extensionFromMime(mimeType);

      var metadata = fb.UploadMetadata(
        contentType: mimeType,
      );

      fb.StorageReference storageReference =
          fb.storage().ref(ref).child(fileName + ".$extension");

      fb.UploadTaskSnapshot uploadTaskSnapshot =
          await storageReference.put(mediaInfo.data, metadata).future;

      Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
      return imageUri;
    } catch (e) {
      print("File Upload Error $e");
      return null;
    }
  }

For Deleting the file:
fb.storage().ref('/').child(filePath).delete();
to know why we have use '/' in ref() check this: https://github.com/FirebaseExtended/firebase-dart/issues/291#issuecomment-570078816

Hey everyone. Cloud Storage on Web is now fully supported 🎉 . Please see the documentation to get started; https://firebase.flutter.dev/docs/storage/overview

Was this page helpful?
0 / 5 - 0 ratings