多文件上传功能实现

在许多Web应用程序中,附件上传是一个常见且重要的功能。本文将介绍如何在HTML页面上实现多文件上传功能,并将文件一次性提交到服务器。这种解决方案完全在客户端进行操作,用户可以选择多个文件,从不同的文件夹中选择文件,应用验证,查看所选文件的缩略图预览,并允许从列表中删除文件。因此,它非常轻量级,因为所有的开销都保留在客户端。

解决方案概述

选择多个文件、从不同文件夹选择文件、对文件扩展名、文件大小和上传文件数量进行验证、以缩略图预览列出所选文件、通过允许删除文件选项过滤所选文件、将选定和过滤后的文件列表保存在JavaScript数组中以提交到服务器。

需要对HTML5、CSS和客户端脚本(JavaScript和JQuery)有基本的了解。

使用代码

技术介绍:HTML5提供了一种标准的方式来处理本地文件,即File API。File API可以用来创建图像的缩略图预览,也可以使用客户端逻辑来验证上传文件的类型、大小和数量。

使用了标准的HTML5控件进行多文件上传。这是上传文件元素的最直接方式。

为了给文件上传控件一个现代的外观,为文件上传父级span添加了一个样式表。

选择附件

用户选择后,JavaScript返回所选的File对象列表作为FileList。为文件上传控件添加了一个事件处理程序来访问FileList属性。

document.addEventListener("DOMContentLoaded", init, false); function init() { document.querySelector('#files').addEventListener('change', handleFileSelect, false); }

然后,事件处理函数:

function handleFileSelect(e) { if (!e.target.files) return; var files = e.target.files; for (var i = 0, f; f = files[i]; i++) { var fileReader = new FileReader(); fileReader.onload = (function(readerEvt) { return function(e) { ApplyFileValidationRules(readerEvt); RenderThumbnail(e, readerEvt); FillAttachmentArray(e, readerEvt); }; })(f); fileReader.readAsDataURL(f); } document.getElementById('files').addEventListener('change', handleFileSelect, false); }

用户选择后,调用fileReader.readAsDataURL()读取文件,并通过设置src属性为数据URL来渲染缩略图。

function RenderThumbnail(e, readerEvt) { var li = document.createElement('li'); ul.appendChild(li); li.innerHTML = [ '
×', '
' ].join(''); var div = document.createElement('div'); div.className = "FileNameCaptionStyle"; li.appendChild(div); div.innerHTML = [readerEvt.name].join(''); document.getElementById('Filelist').insertBefore(ul, null); }

通过为每个图像预览添加×(×在HTML代码中表示x)来添加删除文件的功能。因此,当用户点击红色(x)时,将通过调用下面的Jquery函数将其删除:

jQuery(function($) { $('div').on('click', '.img-wrap .close', function() { var id = $(this).closest('.img-wrap').find('img').data('id'); var elementPos = AttachmentArray.map(function(x) { return x.FileName; }).indexOf(id); if (elementPos !== -1) { AttachmentArray.splice(elementPos, 1); } $(this).parent().find('img').not().remove(); $(this).parent().find('div').not().remove(); $(this).parent().parent().find('div').not().remove(); var lis = document.querySelectorAll('#imgList li'); for (var i = 0; li = lis[i]; i++) { if (li.innerHTML == "") { li.parentNode.removeChild(li); } } }); });

对上传的文件应用了三个验证规则:

function CheckFileType(fileType) { if (fileType == "image/jpeg" || fileType == "image/png" || fileType == "image/gif") { return true; } else { return false; } } function CheckFileSize(fileSize) { if (fileSize < 300000) { return true; } else { return false; } } function CheckFilesCount(AttachmentArray) { var len = 0; for (var i = 0; i < AttachmentArray.length; i++) { if (AttachmentArray[i] !== undefined) { len++; } } if (len > 9) { return false; } else { return true; } }

然后,根据验证规则显示错误消息:

function ApplyFileValidationRules(readerEvt) { if (CheckFileType(readerEvt.type) == false) { alert("The file (" + readerEvt.name + ") does not match the upload conditions, You can only upload jpg/png/gif files"); e.preventDefault(); return; } if (CheckFileSize(readerEvt.size) == false) { alert("The file (" + readerEvt.name + ") does not match the upload conditions, The maximum file size for uploads should not exceed 300 KB"); e.preventDefault(); return; } if (CheckFilesCount(AttachmentArray) == false) { if (!filesCounterAlertStatus) { filesCounterAlertStatus = true; alert("You have added more than 10 files. According to upload conditions, you can upload 10 files maximum"); } e.preventDefault(); return; } }

感兴趣的点

客户端的最终输出将是一个JavaScript数组。可以根据解决方案架构将其发送到服务器端。例如,可以用JSON对象发送它,或者将其保存在HTML隐藏字段中,然后从那里读取。

对于上传规则(文件数量、文件大小和文件类型),建议将其保存在配置文件中,并从那里读取。

如果正在处理大尺寸附件,那么可以添加一个进度条,这也是HTML5支持的。它允许监控文件读取的进度;对于大文件,捕获错误和确定读取完成非常有用。

有关更多信息,请阅读此文。

浏览器兼容性

此控件已在最新版本的Firefox、Internet Explorer、Chrome和Safari上进行了测试。

对于旧版浏览器,可以检查浏览器是否完全支持File API:

if (window.File && window.FileReader && window.FileList && window.Blob) { // Great success! All the File APIs are supported. } else { alert('The File APIs are not fully supported in this browser.'); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485