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('上传失败,请重试'); // }); }; }]);
关键优势说明
- 框架贴合度高:用AngularJS的指令+服务模式,数据和视图自动绑定,无需手动操作DOM,符合MVVM开发习惯
- 性能优化到位:前端提前压缩,避免大文件占用带宽和后端资源,异步处理也不会阻塞页面
- 可扩展性强:如果需要支持非图片文件,只需替换
ImageCompressor服务的逻辑(比如用pako压缩文档类文件) - 复用性好:压缩逻辑封装成服务,指令可以在多个页面直接复用
内容的提问来源于stack exchange,提问作者sathish kumar
相关产品推荐
相关产品推荐

