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

AngularJS与JSFiddle大文件压缩求助:将大文件转至50KB以内

AngularJS 实现大文件压缩上传方案

嘿,我来帮你搞定这个大文件压缩上传的问题!针对你提出的「把5MB/10MB文件压缩到50KB以内」+「解决大文件加载性能问题」的需求,AngularJS可以通过自定义指令结合前端压缩逻辑来实现,比你现在用的jQuery纯校验方案更贴合框架特性,也更易维护复用。

核心思路

  • 用AngularJS自定义指令监听文件选择事件,实时触发文件处理流程
  • 针对图片文件(最常见的大文件上传场景)用canvas做尺寸缩小+质量压缩的双重处理;如果是其他类型文件(如文档),可以扩展对应压缩库
  • 压缩完成后自动校验大小,符合要求才允许提交,从根源避免大文件上传

完整实现代码

1. HTML 部分

<div ng-app="fileUploadApp" ng-controller="UploadController">
  <form class="upload-form" ng-submit="submitForm()">
    <input type="file" 
           file-upload 
           accept="image/*" 
           ng-model="originalFile"
           max-target-size="51200"> <!-- 50KB = 50*1024 = 51200 bytes -->
    <button type="submit" ng-disabled="!compressedFile || sizeError">上传</button>
    <div ng-if="sizeError" style="color:red;">文件压缩后仍超过50KB,请选择更小文件或调整压缩参数</div>
  </form>
</div>

2. AngularJS 代码

angular.module('fileUploadApp', [])
// 自定义文件上传指令:负责文件选择、压缩、校验
.directive('fileUpload', ['$parse', 'ImageCompressor', function($parse, ImageCompressor) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var model = $parse(attrs.ngModel);
      var modelSetter = model.assign;
      var targetSize = parseInt(attrs.maxTargetSize);

      element.bind('change', function(e) {
        scope.$apply(function() {
          var file = e.target.files[0];
          if (!file) return;

          // 仅处理图片文件,非图片可扩展逻辑
          if (!file.type.match('image.*')) {
            alert('请选择图片文件');
            return;
          }

          // 调用压缩服务处理文件
          ImageCompressor.compress(file, targetSize)
            .then(function(compressedBlob) {
              scope.compressedFile = compressedBlob;
              modelSetter(scope, file);
              scope.sizeError = false;
              console.log('压缩完成,大小:', compressedBlob.size, 'bytes');
            })
            .catch(function(msg) {
              scope.sizeError = true;
              console.warn(msg);
            });
        });
      });
    }
  };
}])
// 图片压缩服务:封装可复用的压缩逻辑
.factory('ImageCompressor', [function() {
  return {
    compress: function(file, targetSize) {
      return new Promise(function(resolve, reject) {
        var img = new Image();
        img.src = URL.createObjectURL(file);

        img.onload = function() {
          var canvas = document.createElement('canvas');
          var ctx = canvas.getContext('2d');
          let width = img.width;
          let height = img.height;

          // 第一步:按比例缩小尺寸,先减少像素总量
          const maxSideLength = 800; // 限制最大边长,可根据需求调整
          if (width > maxSideLength || height > maxSideLength) {
            const ratio = maxSideLength / Math.max(width, height);
            width = Math.floor(width * ratio);
            height = Math.floor(height * ratio);
          }

          canvas.width = width;
          canvas.height = height;
          ctx.drawImage(img, 0, 0, width, height);

          // 第二步:逐步降低质量,直到符合大小要求
          let quality = 0.8;
          let attemptCount = 0;
          const maxAttempts = 5;

          function tryCompress() {
            canvas.toBlob(function(generatedBlob) {
              if (generatedBlob.size <= targetSize || attemptCount >= maxAttempts) {
                if (generatedBlob.size <= targetSize) {
                  resolve(generatedBlob);
                } else {
                  reject('无法将文件压缩到目标大小,请尝试更小的文件');
                }
                return;
              }
              quality -= 0.15; // 每次降低15%质量
              attemptCount++;
              tryCompress();
            }, file.type, quality);
          }

          tryCompress();
          URL.revokeObjectURL(img.src); // 释放内存
        };
      });
    }
  };
}])
// 上传控制器
.controller('UploadController', ['$scope', function($scope) {
  $scope.submitForm = function() {
    // 这里将压缩后的文件转为FormData,发送到后端
    const formData = new FormData();
    // 保留原文件名,方便后端识别
    formData.append('uploadFile', $scope.compressedFile, $scope.originalFile.name);

    // 示例:模拟上传请求(替换成你的实际接口)
    console.log('准备上传压缩文件');
    // $http.post('/your-upload-api', formData, {
    //   headers: { 'Content-Type': undefined }
    // }).then(res => {
    //   alert('上传成功');
    // }).catch(err => {
    //   alert('上传失败,请重试');
    // });
  };
}]);

关键优势说明

  1. 框架贴合度高:用AngularJS的指令+服务模式,数据和视图自动绑定,无需手动操作DOM,符合MVVM开发习惯
  2. 性能优化到位:前端提前压缩,避免大文件占用带宽和后端资源,异步处理也不会阻塞页面
  3. 可扩展性强:如果需要支持非图片文件,只需替换ImageCompressor服务的逻辑(比如用pako压缩文档类文件)
  4. 复用性好:压缩逻辑封装成服务,指令可以在多个页面直接复用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:52:42