java文件上传简单实现

1 准备工作

对于文件上传,浏览器在上传的过程中是以流的形式提交到服务器端的。一般选择采用apache的开源工具common-fileUpload这个文件上传组件

common-fileUpload是依赖common-io这个包的,所以还需要下载这个包

2 使用类介绍

注意事项:

  1. 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放在 WEB-INF目录下
  2. 为防止文件覆盖的情况发现,要为上传文件产生一个唯一的文件名
  3. 要限制上传文件的最大值
  4. 可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法

需要用到的类详解:

ServletFileUpload负责处理上传的文件数计,并将表单中每个输入项封装成一个Fileitem对象,在使用ServletFileUpload对象解析请求时需要DiskFileFactory对象,所以,我们需要在进行解析工作前构造好DiskFileitemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性

3 FileItem类

在HTML页面input必须有name
例:

表单如果包含一个文件上传输入项的话,这个表单的enctype就必须设置为multipart/form-data

<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    上传用户:<input type="text" name="username"><br/>
    上传文件1:<input type="file" name="file1"><br/>
    上传文件2:<input type="file" name="file2"><br/>
    <input	type="submit" value="提交">
</form>

浏览器表单的类型如果为multipart/form-data,在服务器端想获得数计就要通过流

常用方法

//isFormFiled方法用于判断FileItem类对象封装的数据是一个普通文本表单
//这是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormFiled();

//getFieldName 方法用于返回表单标签name属性的值
String getFieldName();

//getString 方法用于将FileItem对象中保存的数据类内容以一个字符串返回
String getString();

//getName方法用于获得上传字段中的文件名
String getName();

//以流的形式返回上传文件的数据内容
InputStream getInputStream();

//delete方法用来清空FileItem对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时问题
void delete();

3 ServletFileUpload

负责处理上传文件的数据,将表单中每个输入项封装成FileItem对象中,使用其parseRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回

常用方法:一个对象名为upload

  • upload.setHeaderEncoding(“UTF-8”); 乱码问题
  • upload.setFileSizeMax(int len); 设置单个文件最大值
  • upload.setSizeMax(1024102410); 设置总共能够上传文件的大小

4 DiskFileItemFactory

一个可以获得ServletFileUpload类对象的工厂类,可以对于上传的文件做限制

对于大于

常用方法:

  • setSizeThreshold(int len) 设置缓冲区大小
  • setRepository(file2); 临时目录的保存目录,需要一个File对象

5 示例

前端页面核心代码:

<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
  上传用户:<input type="text" name="username"><br/>
  上传文件1:<input type="file" name="file1"><br/>
  上传文件2:<input type="file" name="file2"><br/>
  <input   type="submit" value="提交">
</form>

请求的searvlet

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

//几个步骤可以选择封装成方法
public class FileUploadServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        //判断上传的文件是普通表单还是带文件的表单
        if (!ServletFileUpload.isMultipartContent(request)){//如果是一个普通的表单
            return;//终止方法运行
        }
        //创建上传文件的保存路径,建议保存在web-inf下面,安全,用户无法直接访问上传的文件
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File file = new File(uploadPath);
        if (!file.exists()){
            file.mkdir();//创建这个目录
        }
        //缓存,临时文件
        //临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自动删除,或者提醒用户转存为永久
        String temp = this.getServletContext().getRealPath("/WEB-INF/temp");
        File file2 = new File(temp);
        if (!file2.exists()){
            file2.mkdir();//创建这个目录
        }

        //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
        factory.setSizeThreshold(1024*1024);//缓冲区大小为1M
        factory.setRepository(file2);//临时目录的保存目录,需要一个File

        //2.获取ServletFileUpload
        ServletFileUpload upload = new ServletFileUpload(factory);

        //监听文件上传进度
        upload.setProgressListener(new ProgressListener() {
            public void update(long l, long l1, int i) {
                System.out.println("总大小:"+l1+"已上传:"+l);
            }
        });
        //处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024*1024*10);
        //设置总共能够上传文件的大小
        upload.setSizeMax(1024*1024*10);

        //3.处理上传的文件
        //把前端请求解析,封装成一个FileItem对象
        try {
            List<FileItem> fileItems = upload.parseRequest(request);

            for (FileItem fileItem : fileItems) {
                //判断上传的表单是不是带文件的表单
                if (fileItem.isFormField()){//这不是文件
                    //getFileName指的是前端表单控件的name
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString("UTF-8");//处理乱码
                    System.out.println(name+":"+value);
                }else {//这是文件
                    //1、处理文件
                    String name = fileItem.getName();
                    //可能存在文件名不合法
                    if (name.trim().equals("")||name==null){
                        continue;
                    }
                    //获得上传的文件名 /**/**/**.mp4
                    String fileName = name.substring(name.lastIndexOf("/") + 1);
                    //获得文件的后缀名
                    String fileExtName = fileName.substring(fileName.lastIndexOf(".") + 1);

                    //判断后缀名。如果我们不需要这样的,就直接return,告诉用户类型不对
                    //省略判断文件类型

                    //可以利用uuid来保证文件名唯一
                    //UUID.randomUUID(),随机生成一个唯一识别的通用码

                    //网络传输中的东西都需要序列化
                    //POJO实体类,如果想要在多个电脑上运行,需要把对象序列化
                    //implements Serializable:标记接口,JVM--》本地方法站 native-->native
                    String uuidPath = UUID.randomUUID().toString();


                    //2、存放地址
                    //存到哪里 uploadPath
                    //文件真实存在的路径 realPath
                    String realPath = uploadPath + "/" + uuidPath;
                    //给每个文件创建一个对于的文件夹
                    File realPathFile = new File(realPath);
                    if (!realPathFile.exists()){
                        realPathFile.mkdir();
                    }

                    //3、文件传输
                    //获得上传文件的流
                    InputStream is = fileItem.getInputStream();
                    //创造一个文件输出流
                    FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                    //创造一个缓冲区
                    byte[] buffer = new byte[1024 * 1024];
                    //开始传输
                    int len=0;
                    while((len=is.read(buffer))!=-1){
                        fos.write(buffer,0,len);
                    }
                    //关闭流
                    fos.close();
                    is.close();
                    //清除临时文件
                    fileItem.delete();
                    //返回消息 msg = "文件上传成功"
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值