java中用I/O流实现文件上传

依赖添加

需要添加以下两个依赖

<dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.3.1</version>
</dependency>
   <dependency>
   <groupId>commons-io</groupId>
   <artifactId>commons-io</artifactId>
   <version>2.6</version>
 </dependency>


提交form表单的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/register/02" method="post" enctype="multipart/form-data">
    姓名:<input type="text" name="name"/><br>
    年龄:<input type="text" name="age"/><br>
    照片:<input type="file" name="file"/><br>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

表单中的name和age为普通表单项,file为文件表单项


配置中排除MultipartAutoConfiguration类

因为springboot已经自动配置了MultipartResolver ,导致上传的文件表单项被过滤掉,List fileItems = upload.parseRequest(request)中的list会清0,所有必须在配置中排除MultipartAutoConfiguration类,如下

@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

下面介绍两种编写Controller的方法:

1.控制器(不借助框架,实现文件上传)

@Controller
@RequestMapping("/register")
public class RegisterController {

    @RequestMapping("/01")
    public void Test01(HttpServletRequest request, HttpServletResponse response) throws IOException, FileUploadException {
        //判断请求是否为Multipart请求
        if(!ServletFileUpload.isMultipartContent(request)){
            throw new RuntimeException("当前请求文件不支持文件上传!");
        }
        //创建一个FileItem工厂
        DiskFileItemFactory factory=new DiskFileItemFactory();

        //设置使用临时文件的阀值
        factory.setSizeThreshold(1024*1024*1);

        //设置一个临时文件,当上传的文件大小超过阀值时,文本创建文件的副本保存在临时文件中
        String tempPath="F:\\temp";
        File tempFile=new File(tempPath);
        factory.setRepository(tempFile);

        //创建文件上传核心组件
        ServletFileUpload upload=new ServletFileUpload(factory);

        //设置每一个item的头部字符编码,其可以解决文件名的中文乱码问题
        upload.setHeaderEncoding("UTF-8");

        //设置单个上传文件的最大边界值为2M
        upload.setFileSizeMax(1024*1024*2);

        //设置一次上传所有文件的总大小的最大值为5M(对于上传多个文件时起作用)
        upload.setSizeMax(1024*1024*5);

        //解析请求
        List<FileItem> fileItems = upload.parseRequest(request);
        for(FileItem item:fileItems){
            if(item.isFormField()){//若item为普通表单项
                String fieldName = item.getFieldName();
                String fileValue = item.getString("UTF-8");
                System.out.println(fieldName+" = "+fileValue);
            }else {//若item为文件表单项
                String fileName=item.getName();//获取上传文件的原始名称
                fileName=System.currentTimeMillis()+fileName;
                //获取输入流,其中有上传文件的内容
                InputStream inputStream=item.getInputStream();
                //获取文件保存在服务器的路径
                String path="F:/demo/images";

/*
*设置文件的分级目录管理,将多个文件存放在不同的目录中
*以下方法时按日期进行目录管理,例如D:/file/2021/2/4。
*/
                //获取当前系统时间
                Calendar nowDate=Calendar.getInstance();
                //获取年、月、日
                int year=nowDate.get(Calendar.YEAR);
                int month=nowDate.get(Calendar.MONTH)+1;
                int day=nowDate.get(Calendar.DAY_OF_MONTH);

                path=path+"/"+year+"/"+month+"/"+day;

                //若该目录不存在,则创建该目录
                File dir=new File(path);
                if(!dir.exists()){
                    dir.mkdirs();
                }

                //创建目标文件,用于保存上传的文件
                File file=new File(path,fileName);
                //创建文件输出流
                OutputStream outputStream=new FileOutputStream(file);
                //将输入流的数据写入到输出流中
                int len=-1;
                byte[] buffer=new byte[1024];
                while((len=inputStream.read(buffer))!=-1){
                    outputStream.write(buffer,0,len);
                }
                //关闭流
                outputStream.close();
                inputStream.close();

                //删除临时文件
                item.delete();
            }
        }
    }

2.控制器(使用MultipartFile,推荐)

注意:使用这种方法时,必须将前面的排除MultipartAutoConfiguration类的配置关掉,重新应用此类。

@RequestMapping("/02")
    public  String  fileUpload( @RequestParam("file") MultipartFile file,String name,Integer age)  throws  IOException{
        //用来检测程序运行时间
        long   startTime=System.currentTimeMillis();
        System.out.println( "fileName:" +file.getOriginalFilename());
        
        String filename =file.getOriginalFilename();
        //获取文件保存在服务器的路径
        String path="F:/demo/images";

        //获取当前系统时间
        Calendar nowDate=Calendar.getInstance();
        //获取年、月、日
        int year=nowDate.get(Calendar.YEAR);
        int month=nowDate.get(Calendar.MONTH)+1;
        int day=nowDate.get(Calendar.DAY_OF_MONTH);

        path=path+"/"+year+"/"+month+"/"+day;

        //若该目录不存在,则创建该目录
        File dir=new File(path);
        if(!dir.exists()){
            dir.mkdirs();
        }
        //文件传输工具类
        FtpUtil ftpUtil=new FtpUtil();
        ftpUtil.uploadHttpFile(path,filename,file.getInputStream());
        long   endTime=System.currentTimeMillis();
        System.out.println( "采用流上传的方式的运行时间:" +String.valueOf(endTime-startTime)+ "ms" );
        //若文件上传成功,则跳转到“文件上传成功”页面
        return  "/success" ;
    }

//上面使用了FtpUtil工具类中的uploadHttpFile方法,将一些样本化的代码进行了封装,如下:
public boolean uploadHttpFile(String filePath, String filename, InputStream input) {
		boolean result = false;
		FileOutputStream fos = null;
		try {
			File file = new File(filePath);
			if(!file.exists()) {
				file.mkdir();
			}			
			fos = new FileOutputStream(filePath + "/"  + filename);
			byte[] buffer = new byte[1024];
			int length;
			while ((length = input.read(buffer)) != -1) {
				fos.write(buffer, 0, length);
			}
			input.close();
			fos.close();
			result = true;
		} catch (IOException e) {
			logger.error(e.getMessage());
			throw new RuntimeException();
		} finally {
			try {
				if (input != null) {
					input.close();
				}
				if (fos != null) {
					fos.close();
				}
			} catch (IOException ignored) {
			}
		}
		return result;
	}

可以看出第二种方法编写controller更为简洁

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值