ssm框架实现Excel文件上传,保存文件功能

实现文件上传的方式用很多种,文件类型也有许多种类,这篇文章主要针对Excel进行解析,这里解析文件使用的是spring框架自带的类进行解析。首先,有几个点需要知道,用户上传的excel文件,前端如何保存该文件并发送给后端,后端控制器如何获取文件并解析,持久层如何保存文件数据,这是我们需要知道的大致流程,这里从持久层写到视图层,有点逆向思维,那我们开始吧!

首先导入相关依赖
pom依赖

//POI提供API给Java程序对Microsoft Office格式档案读和写的功能
<!--poi依赖-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.15</version>
</dependency>

<!-- 接收文件上传依赖 -->
 <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
 </dependency>

从持久层开始分析,对保存数据而言,用户上传的数据肯定不止一行数据,那么可以封装集合进行批量保存,集合有很多种,根据分析进行选择,这里最适合选择list集合来保存数据,这里确定后,控制层也几乎确定了。

mapper层的sql语句,参数类型是list集合中的具体对象的参数类型,这里类型也可以可list,都是正确的,这里建议写具体参数类型,因为文档中是写具体类型,使用动态sql把集合中的对象都遍历出来,赋值给obj,这里的obj只是自己设置的参数名,obj代表集合中的对象,将对象的属性都放到插值表达式中,完成数据的添加。

<insert id="insertImportExcel"  parameterType="com.chen.domain.Activity">
     insert into tbl_activity(id, owner, name, cost, description )
     values
     <foreach collection="list" separator="," item="obj">
        (#{obj.id},#{obj.owner},#{obj.name},#{obj.cost},#{obj.description})
     </foreach>
</insert>

service调用mapper层

@Service
public class ActivityServiceImpl{
     //注入mapper层
     @Autowired
     ActivityMapper activityMapper;
     
     @Override
     public int insertImportExcel(List<Activity> list) {
          return activityMapper.insertImportExcel(list);
     }
}

springMVC注册文件上传解析器

//这里需要注意的是id名称必须为multipartResolver,不然springMVC无法识别
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    //设置字符集
    <property name="defaultEncoding" value="utf-8"/>
    //设置最大接收大小
    <property name="maxUploadSize" value="#{1024*1024*80}"/>
</bean>

接收前端excel文件

@Controller
public class ActivityController {

@Autowired
ActivityService activityService;
/**
 * 导入活动列表
 * MultipartFile 该对象用于接收前端传来的文件
 * 使用该对象接收文件需要在springMvc配置信息中注册文件上传解析器CommonsMultipartResolver
 * HttpSession 当前会话
 * @return 返回保存成功或失败提示信息
 */
@RequestMapping("/activity/importActivities.do")
@ResponseBody
public Object importActivities(MultipartFile file, HttpSession session) throws Exception {
    //创建一个文件对象,并以流的方式读取该文件
    HSSFWorkbook wb = new HSSFWorkbook(file.getInputStream());
    //当前登录用户
    User user = (User) session.getAttribute(Changeful.USER_SESSION_NAME);
    //获取文件对象中的页对象,0表示第一页,1表示第二页,依次类推...
    HSSFSheet sheetAt = wb.getSheetAt(0);
    //在循环外定义空引用
    HSSFRow row = null;
    HSSFCell cell = null;
    Activity activity = null;
    List<Activity> activityList = new ArrayList<>();
    //将页中的每一行循环出来,从第二行开始获取数据
    //第一行是描述整列的信息,不用保存到数据库
    //sheetAt.getLastRowNum()获取最后行数,这里注意是小于等于
    for (int i = 1; i <= sheetAt.getLastRowNum(); i++) {
        //获取行对象
        row = sheetAt.getRow(i);
        //设置主键值及上传文件者
        activity = new Activity();
        activity.setId(UUIDUtil.getUUID());//设置主键
        activity.setOwner(user.getId());//设置所有者
        
        //将行中的每一列数据循环出来
        for (int j = 0; j < row.getLastCellNum(); j++) {
            cell = row.getCell(j);
            //因为excel每个单元格有数据类型,且与java中数据类型有些不同
            //所有封装一个工具类用于判断excel的数据类型
            //使用工具类确定列的类型
            switch (j) {
                case 0:
                    activity.setName(ExcelCellValueTypeUtil.getCellValue(cell));
                case 1:
                    activity.setStartDate(ExcelCellValueTypeUtil.getCellValue(cell));
                case 2:
                    activity.setEndDate(ExcelCellValueTypeUtil.getCellValue(cell));
                case 3:
                    activity.setCost(ExcelCellValueTypeUtil.getCellValue(cell));
                case 4:
                    activity.setDescription(ExcelCellValueTypeUtil.getCellValue(cell));
            }
        }
        //每列循环完获取到一个活动对象,添加到list集合中
        activityList.add(activity);
    }
    //返回添加条数,返回给前台
    int count = activityService.insertImportExcel(activityList);

    ReturnJson returnJson = new ReturnJson();
    //简单的判断,如果添加条数大于1行,表示上传成功
    if (count>0){
        returnJson.setCode(Changeful.RETURN_JSON_CODE_SUCCESS_STATUS);
        returnJson.setObject(count);
    }else {
        returnJson.setCode(Changeful.RETURN_JSON_CODE_FAILURE_STATUS);
        returnJson.setMessage("系统繁忙,请稍后重试!");
    }
    return returnJson;
    }
}

用于判断excel中表中列的数据类型工具类

//将excel中的数据都转换成字符串类型,这样较容易的保存
public class ExcelCellValueTypeUtil {
    public static String getCellValue(HSSFCell cell) {
        String value = "";
        switch (cell.getCellType()) {
            case HSSFCell.CELL_TYPE_NUMERIC:
                value = cell.getNumericCellValue() + "";
                break;
            case HSSFCell.CELL_TYPE_STRING:
                value = cell.getStringCellValue();
                break;
            case HSSFCell.CELL_TYPE_BOOLEAN:
                value = cell.getBooleanCellValue() + "";
                break;
            case HSSFCell.CELL_TYPE_FORMULA:
                value = cell.getCellFormula();
                break;
            default:
                value = "";
        }
        return value;
    }
}

后端代码完成之后,来看看前端如何获取文件吧!

//点击导入市场活动按钮
<script type="text/javascript">
$(function () {
	$("#importActivityBtn").click(function () {
	    //截取文件结尾,判断是否为xls文件
	    var val = $("#activityFile").val().substr($("#activityFile").val().lastIndexOf(".")+1).toLowerCase();
	    if ("xls"!=val){
	        alert("只支持.xls格式!");
	        return;
	    }
	    //当用户选择文件后,前端会将该文件保存在dom对象中
	    //获取该节点的dom对象,再获取files中的第一个文件
	    //files可以保存多个用户上传文件,相当于一个数组,但是当下大部分浏览器只支持上传一个文件,所有获取该数组中的第一个文件对象
	    var file = $("#activityFile").get(0).files[0];
	    //判断文件大小
	    if(file.size>1024*1024*5){
	        alert("文件大小不超过5MB!");
	        return;
	    }
	    //这里上传文件和平时携带参数有所不同,需要创建formData 对象才能将文件传送到后台
	    var formData = new FormData();
	    formData.append("file",file);
	    //发送异步请求
	    $.ajax({
	        url: "workbench/activity/importActivities.do",
	        data:formData,
	        contentType:false,//默认请求下,ajax每次向后台发送请求,都会把所有的参数统一进行urlencoded编码,设置contentType=false,可以阻止这种行为
	        processData:false,//默认请求下,ajax每次向后台发送请求,都会把多有的参数统一转化成字符串,设置processData=false,可以阻止这种行为
	        type: 'post',
	        dataType: "json",
	        success: function (data) {
	            if (data.code==1){
	                //导入成功,提示成功导入记录条数,关闭模态窗口,刷新活动列表,显示第一页数据,保持每页显示条数不变
	                alert("成功导入"+data.object+"条市场活动");
	                $("#importActivityModal").modal("hide");
	                //这里调用的是分页插件
	                queryActivityMethod(1, $("#turnPage").bs_pagination('getOption', 'rowsPerPage'));
	            }else{
	                //导入失败,提示信息,模态窗口不关闭,列表也不刷新
	                alert(data.message);
	                $("#importActivityModal").modal("show")
	            }
	        }
	    })
	});
    }
</script>	

//这里注意:上传文件只能类型为type="file",不然前端将无法获取文件对象
<div class="modal-body" style="height: 350px;">
    <div style="position: relative;top: 20px; left: 50px;">
        请选择要上传的文件:<small style="color: gray;">[仅支持.xls或.xlsx格式]</small>
    </div>
    <div style="position: relative;top: 40px; left: 50px;">
        <input type="file" name="file" id="activityFile">
    </div>
    <div style="position: relative; width: 400px; height: 320px; left: 45% ; top: -40px;">
        <h3 style="color: red"> 重要提示:</h3>
        <ul>
            <li>操作仅针对Excel,仅支持后缀名为XLS/XLSX的文件。</li>
            <li>给定文件的第一行将视为字段名。</li>
            <li>请确认您的文件大小不超过5MB。</li>
            <li>日期值以文本形式保存,必须符合yyyy-MM-dd格式。</li>
            <li>日期时间以文本形式保存,必须符合yyyy-MM-dd HH:mm:ss的格式。</li>
            <li>默认情况下,字符编码是UTF-8 (统一码),请确保您导入的文件使用的是正确的字符编码方式。</li>
            <li>建议您在导入真实数据之前用测试文件测试文件导入功能。</li>
        </ul>
    </div>
</div>

至此,从后台到前台的代码已经完成,但还有很多不足的地方,需要根据客户进行完善,根据客户需求进行开发,那么,感谢你的观看,有错误的地方,请帮忙指出,感激不尽!!!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值