黑马小日子--文件上传

文件上传

一、文件上传入门

1. 应用:

 用户上传头像、上传图片、邮件上传附件等

 

2. 页面表单的实现

    文件上传表单和普通表单有两个区别

    1) 需要文件上传字段  <input type=”file” />

    2) form 表单的 enctype 属性需要指定为 multipart/form-data

    3) 文件的提交方式必须为POST

<form action="${pageContext.request.contextPath}/servlet/UploadServlet3" method="post" enctype="multipart/form-data">

    用户名:<input type="text" name="username"/><br/>

    文件1<input type="file" name="file1"/><br/>

    文件2<input type="file" name="file2"/><br/>

    <input type="submit" value="上传"/>

3. 服务器端解析request

    在 Servlet 中通过request.getInputStream 获得表单上传数据,会发现数据是分段发送的

使用Apache 开发的开源组件Commons-fileupload需要导入 jar 包Commons-fileupload 和Commons-io 

 

3      . UploadServlet 中处理文件上传程序

所需类:1  工厂类:DiskFileItemFactory

2        负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中:ServletFileUpload

3        代表字段的类: FileItem

// 1. 创建工厂类

DiskFileItemFactory factory = new DiskFileItemFactory();

// 2. 创建FileUpload对象

ServletFileUpload upload = new ServletFileUpload(factory);

// 3. 判断是否是上传表单

boolean b = upload.isMultipartContent(request);

if(!b) {

    // 不是文件上传

request.setAttribute("message", "对不起,不是文件上传表单!");

request.getRequestDispatcher("/message.jsp").forward(request, response);

    return;

}

// 是文件上传表单

// 4. 解析request,获得FileItem项

List<FileItem> fileitems = upload.parseRequest(request);

// 5. 遍历集合

for(FileItem item : fileitems) {

    // 判断是不是普通字段

if(item.isFormField()) {

    String name = item.getFieldName();

    String value = item.getString();

    // 手工的转换了

    value = new String(value.getBytes("iso-8859-1"),"utf-8");

    System.out.println(name + "=" + value);

}

 else {

    // 文件上传字段

    // 获得文件名

    String filename = item.getName();

    System.out.println(filename);

    filename = filename.substring(filename.lastIndexOf("\\")+1);

    

    System.out.println(filename);

    // 创建文件

    ServletContext context = getServletContext();

    String dir = context.getRealPath("WEN-INF/upload");

    File file = new File(dir, filename);

    file.createNewFile();

    

    // 获得流,读取数据写入文件

    InputStream in = item.getInputStream();

    FileOutputStream fos = new FileOutputStream(file);

    

    int len;

    byte[] buffer = new byte[1024];

    while((len=in.read(buffer))>0)

        fos.write(buffer,0,len);

    fos.close();

    in.close();

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

}

二、 文件上传处理细节

1. 中文乱码问题

    1) 文件名中文乱码问题,解决办法:告诉文件上传组件以什么编码方式来解码文件名

        ServletUpload.setCharacterEncoding(“utf-8”);

        request. setCharacterEncoding(“utf-8”);    

    2) 普通字段中文乱码问题

        fileitem.getString(“utf-8”);      

2.      临时文件

    对于大文件不能缓存在内存,需要缓存到硬盘,为了方便管理,我们需要设置临时文件存放目录

         public void setSizeThreshold(int sizeThreshold) 

         设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。

 

         public void setRepository(java.io.File repository) 

         指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").

文件上传完毕需要删除临时文件,否则会导致服务器存在两份上传文件

// 注意,需要先将流进行关闭,否则会导致临时文件无法删除

out.close();

in.close();

// 删除临时文件

fileitem.delete();

3. 文件存放目录

    1) 目录需要隐藏,禁止外界直接访问

    2) 文件名需要保证不重复

    3) 文件应该分目录存放

4、多次上传同名文件的覆盖

上传的文件如果名称不同就不会覆盖。3298432984_a.txt

UUID_源文件名

5、如何防止同一目录下文件太多的问题

打撒后存储

利用文件名的hash码打散存储

6、上传文件的大小控制(单个文件和总大小),及如何友好提示用户

单个文件:

ServletFileUpload setFileSizeMax(long)字节

抓异常:FileUploadBase.FileSizeLimitExceededException

 

总大小:

ServletFileUpload setSizeMax

抓异常:FileUploadBase.SizeLimitExceededException

 

7、限制上传文件的类型

不能严格的控制。可通过判断上传文件的扩展名。

8、监听文件的上传进度

注册监听器

upload.setProgressListener(new ProgressListener() {

                //pBytesRead已上传数据的大小

                //pContentLength文件总大小

                //pItems上传的第几个

                public void update(long pBytesRead, long pContentLength, int pItems) {

                    System.out.println("已上传数据的大小"+pBytesRead+",总大小"+pContentLength);

                }

            });

9、用户没有选择文件上传时的问题

if(item==null)
       continue;  //防止用户没有上传文件时,点击上传出现的异常情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值