AngularJS结合Bootstrap-fileinput实现多文件上传与状态管理

作者:小满

时间:2026-10-30

浏览:376

本文介绍如何在AngularJS项目中利用Bootstrap-fileinput插件实现多文件上传、加载与删除功能。通过定义已选择、已上传、已保存三种状态,结合selectedPics数组与data-fileindex属性,解决文件删除后索引错乱问题,并演示如何与JFinal后端交互完成数据库持久化。

文章目录

多文件上传与管理需求分析

在最近的一个项目中,我们需要实现多文件上传与管理功能。由于项目基于Bootstrap开发,经过对比多种Bootstrap文件上传插件,最终选择了bootstrap-fileinput,因其界面美观且支持多文件管理(插件官方地址:http://plugins.krajee.com/file-input)。具体效果如下:

 多文件上传与管理需求分析

(注:bootstrap-fileinput不仅限于图片上传,也支持普通文件上传。鉴于图片缩略图更易于辨识,本文以图片上传为例进行说明。)

关于该插件的基本操作,可参考《JS文件上传神器bootstrap fileinput详解》一文。本文重点在于多文件的管理逻辑。

在介绍插件用法之前,先明确项目中对图片管理的具体需求:

1、支持上传多个图片;

2、仅当点击保存按钮时,图片信息才持久化至数据库;

3、支持加载已保存至数据库的图片信息,并提供删除功能。

基于上述需求,我们将文件状态划分为以下三类:

已选择:图片已放入插件界面,但尚未上传至服务器。如上图第3张图片所示,其下方显示有上传按钮。

已上传:图片已上传至服务器,但图片信息尚未保存至数据库。如上图第2张图片所示,其下方显示进度条为100%。

已保存:图片信息已保存至数据库。如上图第1张图片所示,其下方显示有删除按钮,点击即可从数据库中删除该图片信息。

引入必要文件与基础配置

一、引入必要文件


<link href="<%=path%>/static/css/bootstrap-3.3.5/bootstrap.min.css" rel="stylesheet">
<link href="<%=path%>/static/css/bootstrap-3.3.5/fileinput.css" rel="stylesheet">

<script src="<%=path%>/static/js/jquery-1.11.3.js"></script>
<script src="<%=path%>/static/js/angularjs-1.3.9/angular.min.js"></script>
<script src="<%=path%>/static/js/bootstrap-3.3.5/bootstrap.min.js"></script>
<script src="<%=path%>/static/js/bootstrap-3.3.5/fileinput.js"></script>
<script src="<%=path%>/static/js/bootstrap-3.3.5/fileinput_locale_zh.js"></script>

 

其中fileinput.js和fileinput_locale_zh.js均包含在插件官方包中,angular.min.js和bootstrap.min.js为常规依赖,此处不再赘述。

多文件上传实现

二、多文件上传实现

首先在页面中定义文件控件:

<input id="input-images" type="file" multiple class="file-loading" accept="image/*">

随后对该控件进行初始化,即可实现多文件上传功能:


 $("#input-images").fileinput({
  uploadUrl: "<%=path%>" + "/album/pictureFileUpload",
  allowedFileExtensions: ["jpg", "png", "gif"],
  resizePreference: 'height',
  maxFileCount: 10,
  language: 'zh',
  overwriteInitial: false,
  resizeImage: true,
  });

初始化时包含诸多属性,此处不一一列举。后台代码(使用JFinal框架)如下:


 public void pictureFileUpload() {
 UploadFile uploadFile = getFile();
 renderJson("{\"link\":" + "\"/fileinput/upload/" + uploadFile.getFileName()
 + "\"" + ",\"fileName\":\"" + uploadFile.getOriginalFileName()
 + "\"}");
 }

注意:后端必须返回Json格式数据,即使为空JSON串(“{}”)也可。该返回值将保存在前台的data.response中。

已有文件的加载与删除

三、已有文件的加载与删除

已有文件的加载旨在展示服务器上已存在的文件,以实现文件管理并提供删除功能,这主要依赖于initialPreview属性。

获取服务器上的文件名称和地址后,使用initialPreview和initialPreviewConfig完成加载及删除操作的定义:


var initPreview = new Array();//展示元素
 var initPreviewConfig = new Array();//展示设置
 
 $.post(
 "<%=path%>" + "/album/getPicsByAlbum", 
 {albumId : albumId}, 
 function(result) {
 for(var i=0;i<result.length;i++){
   var pictureFile = result[i];
 //用于展示已经上传的图片
  initPreview.push("<img src='" + pictureFile.PICADDRESS 
   + "' class='file-preview-image' alt='"+pictureFile.PICNAME+"' title='"+pictureFile.PICNAME+"'>");
  var config = new Object();
  config.caption = pictureFile.PICNAME;
  config.url="<%=path%>" + "/album/deletePicById";
  config.key=pictureFile.ID;
  initPreviewConfig.push(config);
 }
 initFileInput($scope);
  $("#input-images").fileinput('refresh', {
  initialPreview: initPreview,
  initialPreviewConfig: initPreviewConfig
  });
 }
 );

点击删除图标时,默认会将config中的key值传递至后台,后台需定义deletePicById方法进行处理:


 public void deletePicById() {
 String picId = getPara("key");
 service.deletePicById(Integer.valueOf(picId));
 renderJson("{}");
 }

关键问题解答

四、几点疑问的解答

1、为什么model里没有属性,却可以在前端展示相关属性? 这里主要使用了JFinal的ActiveRecord功能,无需定义属性和setter、getter方法,属性值被映射在model里的attrs中,该属性是<key, value>的键值对,key即为数据库字段名。特别提醒:虽然SQL语句不区分大小写,但字段名存在大小写敏感。若字段名为大写,映射到model里的key也将是大写。同时,JFinal默认的主键策略可能失效,需在configPlugin中设置,例如:arp.addMapping("pictures", "ID", Picture.class)。建议大家遵循Java命名规范命名数据库字段。

2、(参考代码)中初始化FileInput时为何要执行clear、destroy操作?

因为FileInput插件在选择文件后,无论是否上传,都会保留文件在file域中。再次点击时会显示上一次选择的文件,这不符合多相册管理的需求。原本以为clear操作即可清空file域(官方文档如此说明),但实际操作发现并未生效,因此才调用clear、destroy后再重新初始化文件上传控件。(这一点尚存疑,希望有大神指点。)

3、保存时如何知道哪些图片需要存入数据库?这是基于什么实现的?

$scope上有一个selectedPics数组,该属性负责保存最终需存入数据库的文件。文件选择后,选择的信息会保存至该数组,但hasUpload属性为false;文件上传后,对应的hasUpload会被修改为true;上传成功后执行删除(尚未保存至数据库)会从数组中移除对应元素。有人可能会问:若选择文件后不上传直接删除,文件信息是否会占用数据位置从而导致元素错乱?其实并不会。在fileuploaded事件中,哪些图片已hasUpload,是直接修改数组对应位置元素的值。数组坐标通过图片所在DIV的data-fileindex属性值获得,该值会一直递增,不会替补空缺值,也不会因删除图片而变动,正好与selectedPics数组相对应。 var idx = $("#"+previewId).attr("data-fileindex"); 例如,我选择了3张图片,此时未上传,它们依次对应的data-fileindex为0、1、2。当我删除中间那张图片并重新选择新图片时,它们的data-fileindex将变为0、2、3。

五、代码参考 本人初学AngularJS,代码编写尚不够纯熟,如有不妥之处,欢迎大家留言指正。示例代码见文章末尾,数据库脚本为files.sql(MySQL),请大家多参考代码。

源码下载:http://xiazai.jb51.net/201611/yuanma/BSfileinput(jb51.net).rar

如果大家还想深入学习,可以点击这里进行学习,再为大家附两个精彩的专题:Bootstrap学习教程 Bootstrap实战教程

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章