Spring文件上传,包括一次选中多个文件

为方便演示, 所有处理逻辑全部放在Controller完成, 不再写Service等各层接口及实现. 如需在Service层处理, 思路及方法也是完全一样的.


先说前台. 运行以后就是这样子的. 一个非常简单的表单页面, 两个文件上传按钮, 一个提交



其中单个文件上传, 即只能选择一个文件, 无法同时选择多个



相对的, 多个文件就是可以同时选择多个文件了



文件选择以后就是这个样子



代码如下: 一个form, 文件上传就是一个<input>输入, 属性type="file". 此时只能选择单个文件. 而后面加一个multiple, 即可同时选择多个文件


action属性中的路径后缀为.htm, 是因为我的环境中配置了映射, 所以要在Controller中指定的路径后添加一个.htm后缀, 否则系统会报404. 如果没有配置该项则无需添加后缀

<body>
	<form action="${pageContext.request.contextPath}/test/upload.htm" enctype="multipart/form-data" method="post">
		单个文件: <input type="file" name="fileTest"><br/>
		多个文件: <input type="file" name="fileList" multiple/></br/>
		<input type="submit" value="提交" />
	</form>
</body>

另一点需要注意的是, 要实现文件上传, form中必须指定属性enctype="multipart/form-data". method属性为"post"


前台就这些东西了, 没什么特殊的. 然后再看后台


首先Spring配置文件中加这么一个bean

<bean id="multipartResolver"
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<!-- 默认编码 -->
	<property name="defaultEncoding" value="utf-8" />
	<!-- 文件大小最大值 -->
	<property name="maxUploadSize" value="10485760" />
	<!-- 内存中的最大值 -->
	<property name="maxInMemorySize" value="40960" />
</bean>


也可以在代码中直接创建对象

CommonsMultipartResolver commonsMultipartResolver = new   CommonsMultipartResolver(request.getSession().getServletContext());

但是个人认为配置以后使用比较方便, 各位根据实际需要来吧


其中maxUploadSize属性用来设计上传文件的最大值, 单位是字节. 注意这里是总的上传限制, 比如设置为10M, 上传了4个3M的文件. 虽然单个文件都在10M以内, 但是总大小已经超过10M限制, 会抛出MaxUploadSizeExceededException异常


package com.test.controller;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

/**
 * 文件上传测试类
 */
@Controller
@RequestMapping("/test")
public class FileUploadController {

    @ResponseBody
    @RequestMapping(value="upload")
    public void testUpload(MultipartHttpServletRequest request) throws IOException {
        /*
         * MultipartHttpServletRequest: 继承于HttpServletRequest以及MultipartRequest.
         * 其中MultipartRequest中定义了相关的访问操作. MultipartHttpServletRequest重写
         * 了HttpServletRequest中的方法, 并进行了扩展. 如果以HttpServletRequest来接收参
         * 数, 则需要先将其转为MultipartHttpServletRequest类型
         * MultipartHttpServletRequest request = (MultipartHttpServletRequest) HttpServletRequest;
         */
        
        /*
         * 再说回刚才的form, 假设我们在单个文件选框中上传了文件1, 多个文件选框中上传了文件2, 3, 4.
         * 那么对于后台接收到的, 可以这么理解, 就是一个Map的形式(实际上它后台真的是以Map来存储的).
         * 这个Map的Key是什么呢? 就是上面<input>标签中的name=""属性. Value则是我们刚才上传的
         * 文件, 通过下面的示例可以看出每一个Value就是一个包含对应文件集合的List
         * 
         * 传到后台接收到的Map就是这样:
         * fileTest: 文件1
         * fileList: 文件2, 文件3, 文件4
         * 
         * 虽然从方法名的表面意义来看是得到文件名, 但实际上这个文件名跟上传的文件本身并没有什么关系.
         * 刚才说了这个Map的Key就是<input>标签中的name=""属性, 所以得到的也就是这个属性的值
         */
        Iterator<String> fileNames = request.getFileNames();
        
        while (fileNames.hasNext()) {
            
            //把fileNames集合中的值打出来
            String fileName=fileNames.next();
            System.out.println("fileName: "+fileName);
            
            /*
             * request.getFiles(fileName)方法即通过fileName这个Key, 得到对应的文件
             * 集合列表. 只是在这个Map中, 文件被包装成MultipartFile类型
             */
            List<MultipartFile> fileList=request.getFiles(fileName);
            
            if (fileList.size()>0) {
                
                //遍历文件列表
                Iterator<MultipartFile> fileIte=fileList.iterator();
                
                while (fileIte.hasNext()) {
                    
                    //获得每一个文件
                    MultipartFile multipartFile=fileIte.next();
                    
                    //获得原文件名
                    String originalFilename = multipartFile.getOriginalFilename();
                    System.out.println("originalFilename: "+originalFilename);
                    
                    //设置保存路径. 
                    String path ="G:/testUpload/";
                    
                    //检查该路径对应的目录是否存在. 如果不存在则创建目录
                    File dir=new File(path);
                    if (!dir.exists()) {
                        dir.mkdirs();
                    }
                    
                    String filePath = path + originalFilename;
                    System.out.println("filePath: "+filePath);
                    
                    //保存文件
                    File dest = new File(filePath);
                    if (!(dest.exists())) {
                        /*
                         * MultipartFile提供了void transferTo(File dest)方法,
                         * 将获取到的文件以File形式传输至指定路径.
                         */
                        multipartFile.transferTo(dest);
                        
                        /*
                         * 如果需对文件进行其他操作, MultipartFile也提供了
                         * InputStream getInputStream()方法获取文件的输入流
                         * 
                         * 例如下面的语句即为通过
                         * org.apache.commons.io.FileUtils提供的
                         * void copyInputStreamToFile(InputStream source, File destination)
                         * 方法, 获取输入流后将其保存至指定路径
                         */
                        //FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), dest);
                    }
                    
                    //MultipartFile也提供了其他一些方法, 用来获取文件的部分属性
                    
                    //获取文件contentType
                    String contentType=multipartFile.getContentType();
                    System.out.println("contentType: "+contentType);
                    
                    /*
                     * 获取name
                     * 其实这个name跟上面提到的getFileName值是一样的,
                     * 就是Map中Key的值. 即前台页面<input>中name=""
                     * 属性. 但是上面的getFileName只是得到这个Map的Key,
                     * 而Spring在处理上传文件的时候会把这个值以name属性
                     * 记录到对应的每一个文件. 如果需要从文件层面获取这个
                     * 值, 则可以使用该方法 
                     */
                    String name=multipartFile.getName();
                    System.out.println("name: "+name);
                    
                    //获取文件大小, 单位为字节
                    long size=multipartFile.getSize();
                    System.out.println("size: "+size);
                    
                    System.out.println("---------------------------------------------------");
                }
            }
        }
    }
}

点击上传后控制台打印出的属性:

fileName: fileTest
originalFilename: jquery-validation-1.14.0.zip
filePath: G:/testUpload/jquery-validation-1.14.0.zip
contentType: application/octet-stream
name: fileTest
size: 879139
---------------------------------------------------
fileName: fileList
originalFilename: ueditor_release_ueditor1_4_3_1-src.zip
filePath: G:/testUpload/ueditor_release_ueditor1_4_3_1-src.zip
contentType: application/octet-stream
name: fileList
size: 4103285
---------------------------------------------------
originalFilename: zookeeper-3.4.8.tar.gz
filePath: G:/testUpload/zookeeper-3.4.8.tar.gz
contentType: application/gzip
name: fileList
size: 22261552
---------------------------------------------------
originalFilename: zTree_v3-master.zip
filePath: G:/testUpload/zTree_v3-master.zip
contentType: application/octet-stream
name: fileList
size: 829706
---------------------------------------------------


查看刚才上传的文件属性, 与打印出的size的值完全符合



  • 15
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值