Firebase Storage v3在Android 4.2.2和4.3上返回“multipart body不包含2或3个部分”

时间:2021-07-13 01:43:15

I am building an Ionic app to deploy on Android 5 and 4. When I try to use a Firebase v3 storage ref (using firebase.js API) to save a Blob on Android 4.2.2 and 4.3 it fails with:

我正在构建一个在Android 5和4上部署的Ionic应用程序。当我尝试使用Firebase v3存储引用(使用firebase.js API)在Android 4.2.2和4.3上保存Blob时,它失败了:

code: "storage/unknown" 
message: "Firebase Storage: An unknown error occurred, please check the error payload for server response." 
serverResponse: "multipart body does not contain 2 or 3 parts." 
name: "FirebaseError"

This works fine on an Android 5.0.1 and 4.4.2 device though.

这虽然适用于Android 5.0.1和4.4.2设备。

Question: Is this a hard limitation of the Android (or included webkit) versions? Or some incompatibility in the firebase.js API I'm using? I'm trying to understand if the problem can be fixed or if nothing can be done.

问题:这是Android(或包含webkit)版本的硬限制吗?或者我正在使用firebase.js API中的一些不兼容性?我试图了解问题是否可以修复或者是否可以做任何事情。

The only other reference to that error message I could find was here: https://github.com/davideast/firebase-react-native-sample/issues/5

我能找到的唯一其他对该错误消息的引用是:https://github.com/davideast/firebase-react-native-sample/issues/5

But seeing as this is an ionic wrapper app, I do have access to the Blob type.

但是看到这是一个离子包装应用程序,我确实可以访问Blob类型。

The file is created by taking a picture using the cordova-plugin-camera extension, saving it to the phones local storage with Camera.DestinationType.FILE_URI

使用cordova-plugin-camera扩展程序拍摄照片创建该文件,使用Camera.DestinationType.FILE_URI将其保存到手机本地存储中

It is then read back into a Blob using the cordova-plugin-file extension before being saved to Firebase Storage (specifically the Google Cloud Store backed storage because this is using firebase v3).

然后使用cordova-plugin-file扩展名将其读回Blob,然后保存到Firebase存储(特别是Google Cloud Store支持的存储,因为它使用的是firebase v3)。

The Blob seems to be created successfully (although it may fall back to using the BlobBuilder if the new Blob constructor is not available - see code snippet)

Blob似乎是成功创建的(尽管如果新的Blob构造函数不可用,它可能会回退到使用BlobBuilder - 请参阅代码片段)

The relevant section of code (from within an AngularJS controller) looks like:

代码的相关部分(来自AngularJS控制器)看起来像:

var makeBlob = function(data, mimeString) {
  try {
    return new Blob([data], {
      type: mimeString
    });
  } catch (err) {
    var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
    var bb = new BlobBuilder();
    bb.append(data);
    return bb.getBlob(mimeString);
  }
};

$scope.uploadLocalImageAsync = function(localImageFileUrl, responseKey, description) {
  var deferred = $q.defer();

  $window.resolveLocalFileSystemURL(localImageFileUrl, function fileEntrySuccess(fileEntry) {
      fileEntry.file(function fileSuccess(file) {
        var reader = new FileReader();
        reader.onloadend = function(evt) {
          try {
            var imageBlob = makeBlob(evt.target.result, 'image/jpeg');
            alert("imageBlob: " + JSON.stringify(imageBlob));

            var metadata = {
              contentType: 'image/jpeg',
              customMetadata: {
                'response': responseKey,
                'description': description
              }
            };

            // Create a root reference
            var storageRef = firebase.storage().ref();
            var fileRef = storageRef.child('images/' + responseKey + '/' + file.name);

            var uploadTask = fileRef.put(imageBlob, metadata);
            uploadTask.on('state_changed', function(snapshot) {
              // Observe state change events such as progress, pause, and resume
              // See below for more detail
              alert(JSON.stringify(snapshot));

            }, function(error) {
              // Handle unsuccessful uploads
              alert(JSON.stringify(error));
              deferred.reject("Upload failed: " + error.code + ": " + error.message)
            }, function() {
              // Handle successful uploads on complete
              // For instance, get the download URL: https://firebasestorage.googleapis.com/...
              var downloadURL = uploadTask.snapshot.downloadURL;
              deferred.resolve({
                gsPath: fileRef.toString(),
                downloadUrl: downloadURL
              });
            });
          } catch (err) {
            deferred.reject("onloadend error: " + err);
          }
        };

        try {
          reader.readAsArrayBuffer(file);
        } catch (err) {
          deferred.reject("readAsArrayBuffer error: " + err);
        }

      }, function fileFailure() {
        deferred.reject("Couldn't make File object");
      });
    },
    function fileEntryFailure() {
      deferred.reject("Couldn't find fileEntry for image");
    });

  return deferred.promise;
};

localImageFileUrl is of the form "file:///storage/sdcard0/Android/data/com.ionicframework.myapp/cache/1471426280702.jpg"

localImageFileUrl的格式为“file:///storage/sdcard0/Android/data/com.ionicframework.myapp/cache/1471426280702.jpg”

The function actually returns a promise which is resolved later in another part of the AngularJS controller.

该函数实际上返回一个promise,稍后在AngularJS控制器的另一部分中解析。

The failure occurs after starting the uploadTask.

启动uploadTask后发生故障。

Again, this works on Android 5.0.1, 4.4.2 but fails on 4.3, 4.2.2

同样,这适用于Android 5.0.1,4.4.2但在4.3,4.2.2上失败

I'm hoping there is some extra setting in Ionic or something that I'm missing. But I really just don't know what is causing the difference in behavior or if there will be anything I can do about it.

我希望在Ionic中有一些额外的设置或者我缺少的东西。但我真的只是不知道是什么导致了行为上的差异,或者是否会有任何关于它的事情。


Things I've tried:

我尝试过的事情:

I've tried downgrading the cordova android platform to 3.5 to target android-17 (4.2.2) specifically (using something similar to here https://*.com/a/32672214/6729807 ) but it produces the same error.

我已经尝试将cordova android平台降级到3.5以专门针对android-17(4.2.2)(使用类似于这里https://*.com/a/32672214/6729807的东西),但它产生相同的错误。

(I also downgraded the different plugins to appropriate levels too)

(我也将不同的插件降级到适当的级别)


Some information on versions of tools being used:

有关正在使用的工具版本的一些信息:

ionic info:

离子信息:

Your system information:

您的系统信息:

Cordova CLI: 6.3.1
Ionic Framework Version: 1.3.1
Ionic CLI Version: 2.0.0
Ionic App Lib Version: 2.0.0-beta.20
OS:
Node Version: v4.4.7

ionic platform version android:

离子平台版android:

Installed platforms:
  android 5.2.1

/platforms/android/AndroidManifest.xml

/platforms/android/AndroidManifest.xml

<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />

/platforms/android/project.properties (and CordovaLib project.properties)

/platforms/android/project.properties(和CordovaLib project.properties)

target=android-23

installed plugins:

安装插件:

cordova-plugin-camera
cordova-plugin-compat
cordova-plugin-file
cordova-plugin-geolocation
cordova-plugin-whitelist

using https://www.gstatic.com/firebasejs/3.3.0/firebase.js

使用https://www.gstatic.com/firebasejs/3.3.0/firebase.js

and https://github.com/firebase/angularfire (release v2.0.1)

和https://github.com/firebase/angularfire(发布v2.0.1)

1 个解决方案

#1


1  

The resolving key was using RNFetchBlob.polyfill.XMLHttpRequest;

import RNFetchBlob from 'react-native-fetch-blob';
const Blob = RNFetchBlob.polyfill.Blob;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;

install package 
- https://github.com/wkh237/react-native-fetch-blob
and execute code
-  https://github.com/wkh237/rn-firebase-storage-upload-sample/blob/master/index.common.js

also read http://*.com/questions/39160006/react-native-firebase-storage-upload-using-putstring-call

#1


1  

The resolving key was using RNFetchBlob.polyfill.XMLHttpRequest;

import RNFetchBlob from 'react-native-fetch-blob';
const Blob = RNFetchBlob.polyfill.Blob;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;

install package 
- https://github.com/wkh237/react-native-fetch-blob
and execute code
-  https://github.com/wkh237/rn-firebase-storage-upload-sample/blob/master/index.common.js

also read http://*.com/questions/39160006/react-native-firebase-storage-upload-using-putstring-call