You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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);
};

几个需要注意的坑

  1. 后端接口兼容性:确保你的服务器接口支持multipart/form-data格式的文件上传,这是FormData默认的编码格式。
  2. Angular Digest循环:所有在XHR回调里更新UI的操作,都要包在$scope.$apply()里,否则Angular无法感知到数据变化。
  3. 路径解析兼容性:resolveLocalFileSystemURL能统一处理iOS和Android的本地文件URI,不要自己手动拼接路径,容易出问题。

内容的提问来源于stack exchange,提问作者Neel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:11:34