使用Servlet3.0完成一个文件上传的功能

文件上传

UploadServlet:
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;UTF-8");
        //接收参数
        //文件描述
        String filedesc = request.getParameter("filedesc");
        System.out.println("文件描述:"+filedesc);
        //接收文件
        Part part = request.getPart("uploadfile");

        long fileSize = part.getSize();//文件大小
        String inputName = part.getName();//input中的name属性名称
        System.out.println("文件大小:"+fileSize);
        System.out.println("input中的name属性名称:"+inputName);

        //获得上传的文件名称
        String header = part.getHeader("Content-Disposition");
        //返回f字母所在的位置
        int idx = header.lastIndexOf("filename=\"");
        //filename="xxx.xxxx";xxx.xxx的位置是idx+10~header.length()-1;
        String fileName = header.substring(idx+10, header.length()-1);
        System.out.println("文件名:"+fileName);

        //获得文件内容
        InputStream is = part.getInputStream();

        //获得文件上传位置uploadFiles的路径:xxx/xxx/uploadFiles
        String path = this.getServletContext().getRealPath("/uploadFiles");

        //获得唯一文件名,不重复
        String uuidFileName = UUIDUtils.getUUIDFilename(fileName);
        //path是uploadFiles的路径,UploadUtils.getPath(uuidFileName)获取的是文件在uploadFiles里面的路径。
        String realPath = path + UploadUtils.getPath(uuidFileName);

        //new File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
        File file = new File(realPath);
        //如果file不存在,在这个路径下创建文件
        if(!file.exists()) {
            file.mkdirs();
        }

        //在realPath下创建名称为uuidFileName的文件。
        OutputStream os = new FileOutputStream(realPath+"/"+uuidFileName);
        byte[] b = new byte[1024];
        int len = 0;
        //read:从输入流读取数据的下一个字节。 值字节被返回作为int范围0至255 。 如果没有字节可用,因为已经到达流的末尾,则返回值-1 。
        while((len = is.read()) != -1) {
            os.write(b, 0, len);
        }
        os.close();

    }
UploadUtils:

目录分离算法解决一个目录下文件过多 :

  • 使用唯一文件名.hashCode(); – 得到一个代表当前这个文件的int类型值.
  • int类型占4个字节32位.可以让hashCode值&0xf; 得到一个int值,用这个int值作为一级目录.
  • 让hashCode右移4位 &0xf ;得到一个int值,用这个int值作为二级目录.依次类推.
package utils;
/**
 * UploadUtils.getPath(uuidFileName)获取的是文件在uploadFiles里面的路径。
 * @author 45度炸
 *
 */
public class UploadUtils {
    public static String getPath(String uuidFileName) {
        //唯一文件名.hashcode()
        int code1 = uuidFileName.hashCode();
        int d1 = code1 & 0xf; //获得一级目录
        int code2 = code1 >>> 4; //右移四位
        int d2 = code2 & 0xf; //获得二级目录
        return "/"+d1+"/"+d2;
    }
}
UUIDUtils:
package utils;

import java.util.UUID;

public class UUIDUtils {
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-","");

    }
/**
 * 获取随机文件名  
 * @param fileName
 * @return
 */
    public static String getUUIDFilename(String fileName) {
        return UUID.randomUUID().toString().replace("-", "")+"_"+fileName;
    }
}
upload.jsp:
  • 表单的提交的方式必须是POST.
  • 表单中需要有文件上传的表单元素:这个元素这个元素必须有name属性和值:
  • 表单的enctype属性的值必须是multipart/form-data.
  <body>
    <form action="/Web16/UploadServlet" method="post" enctype="multipart/form-data">
        <table border="1px" width="600">
            <tr>
                <td>文件描述</td>
                <td><input type="text" name="filedesc"></td>
            </tr>
            <tr>
                <td>文件上传</td>
                <td><input type="file" name="uploadfile"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="上传"></td>
            </tr>
        </table>
    </form>
  </body>

异步请求的Servlet
package Async;

import java.io.IOException;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 异步请求的Servlet
 */

public class AsyncServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        AsyncContext context = request.startAsync(request, response);
        context.start(new MyRunnable(context));
        //输出1-10
        for(int i = 0;i < 10;i++) {
            System.out.println(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }

}


class MyRunnable implements Runnable {

    private AsyncContext context;

    public MyRunnable(AsyncContext context) {
        this.context = context;
    }

    @Override
    //输出a-z
    public void run() {
        for(char i='a';i < 'z';i++) {
            try {
                context.getResponse().getWriter().print(i);
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值