基于XHR替代File Transfer插件实现Ionic Cordova相机文件上传问题
在Ionic 1(Angular 1.3)中用XHR + cordova-plugin-file实现图片上传
我之前在维护Ionic 1老项目时,刚好遇到和你一模一样的问题——弃用file-transfer后完全不知道怎么对接Camera插件返回的图片路径,折腾了好一阵才摸清楚门道,给你一步步拆解具体实现:
第一步:先确保依赖插件安装到位
首先确认你已经安装了cordova-plugin-file,没有的话先执行安装命令:
cordova plugin add cordova-plugin-file
第二步:处理Camera返回的图片路径,转成Blob对象
Camera插件返回的imageUrl可能是file://(Android)或cdvfile://(iOS)这类本地URI,XHR上传需要的是Blob/File对象,所以得用cordova-plugin-file的API解析路径并转换:
$scope.captureAndUpload = function() { const cameraOptions = { quality: 70, destinationType: Camera.DestinationType.FILE_URI, // 必须用FILE_URI,不能用DATA_URL sourceType: Camera.PictureSourceType.CAMERA, encodingType: Camera.EncodingType.JPEG, targetWidth: 1000, targetHeight: 1000, saveToPhotoAlbum: false }; navigator.camera.getPicture( // 拍照成功回调 function(imageUrl) { // 解析本地文件URI window.resolveLocalFileSystemURL(imageUrl, function(fileEntry) { // 获取File对象 fileEntry.file(function(file) { const reader = new FileReader(); reader.onloadend = function(e) { // 将文件转成Blob对象 const blob = new Blob([e.target.result], { type: file.type }); // 调用上传函数 $scope.uploadToServer(blob, file.name); }; reader.readAsArrayBuffer(file); }, function(err) { console.error("读取文件失败:", err); }); }, function(err) { console.error("解析文件路径失败:", err); }); }, // 拍照失败回调 function(err) { console.error("拍照出错:", err); }, cameraOptions ); };
第三步:用XHR + FormData实现上传
拿到Blob对象后,就可以用标准的XHR结合FormData来上传了,和Web端的上传逻辑基本一致:
$scope.uploadToServer = function(blob, fileName) { const xhr = new XMLHttpRequest(); const formData = new FormData(); // 把Blob添加到FormData,这里的"file"要和后端接口的接收字段名一致 formData.append("file", blob, fileName); // 打开上传请求 xhr.open("POST", "你的服务器上传接口地址", true); // 可选:添加请求头,比如身份验证Token // xhr.setRequestHeader("Authorization", "Bearer " + yourAuthToken); // 监听上传进度(可选) xhr.upload.addEventListener("progress", function(e) { if (e.lengthComputable) { const uploadPercent = Math.round((e.loaded / e.total) * 100); console.log(`上传进度:${uploadPercent}%`); // Angular 1.3中更新UI需要手动触发digest循环 $scope.$apply(function() { $scope.uploadProgress = uploadPercent; }); } }); // 监听上传完成 xhr.onload = function() { if (xhr.status === 200) { const res = JSON.parse(xhr.responseText); console.log("上传成功:", res); $scope.$apply(function() { // 处理上传成功后的UI逻辑,比如提示用户 }); } else { console.error(`上传失败,状态码:${xhr.status}`); } }; // 监听上传错误 xhr.onerror = function() { console.error("上传请求发生错误"); }; // 发送请求 xhr.send(formData); };
几个需要注意的坑
- 后端接口兼容性:确保你的服务器接口支持
multipart/form-data格式的文件上传,这是FormData默认的编码格式。 - Angular Digest循环:所有在XHR回调里更新UI的操作,都要包在
$scope.$apply()里,否则Angular无法感知到数据变化。 - 路径解析兼容性:
resolveLocalFileSystemURL能统一处理iOS和Android的本地文件URI,不要自己手动拼接路径,容易出问题。
内容的提问来源于stack exchange,提问作者Neel
相关产品推荐
相关产品推荐

