我正在构建一个 Ionic 应用程序以在 Android 5 和 4 上部署。当我尝试使用 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"
不过,这在 Android 5.0.1 和 4.4.2 设备上运行良好。
问题:这是 Android(或包含的 webkit)版本的硬限制吗?或者我正在使用的 firebase.js API 存在一些不兼容性?我试图了解问题是否可以解决或者是否无能为力。
我能找到的对该错误消息的唯一其他引用是在这里:https://github.com/davideast/firebase-react-native-sample/issues/5 https://github.com/davideast/firebase-react-native-sample/issues/5
但由于这是一个离子包装应用程序,我确实可以访问 Blob 类型。
该文件是通过使用 cordova-plugin-camera 扩展拍照创建的,并使用 Camera.DestinationType.FILE_URI 将其保存到手机本地存储中
然后使用 cordova-plugin-file 扩展名将其读回 Blob,然后保存到 Firebase Storage(特别是 Google Cloud Store 支持的存储,因为它使用 firebase v3)。
Blob 似乎已成功创建(尽管如果新的 Blob 构造函数不可用,它可能会回退到使用 BlobBuilder - 请参阅代码片段)
相关的代码部分(来自 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 的格式为“file:///storage/sdcard0/Android/data/com.ionicframework.myapp/cache/1471426280702.jpg”
该函数实际上返回一个承诺,稍后在 AngularJS 控制器的另一部分中解决该承诺。
启动uploadTask后发生故障。
同样,这适用于 Android 5.0.1、4.4.2,但在 4.3、4.2.2 上失败
我希望 Ionic 中有一些额外的设置或者我缺少的东西。但我真的不知道是什么导致了行为上的差异,或者我是否可以对此做些什么。
我尝试过的事情:
我尝试将 cordova android 平台降级到 3.5 以专门针对 android-17 (4.2.2) (使用类似于此处的内容https://stackoverflow.com/a/32672214/6729807 https://stackoverflow.com/a/32672214/6729807)但它会产生相同的错误。
(我也将不同的插件降级到适当的级别)
有关所使用工具版本的一些信息:
离子信息:
您的系统信息:
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
离子平台版本android:
Installed platforms:
android 5.2.1
/platforms/android/AndroidManifest.xml
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
/platforms/android/project.properties(和 CordovaLib project.properties)
target=android-23
安装的插件:
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
and
https://github.com/firebase/angularfire (release v2.0.1)