文件上传-------fileUpload

来源:互联网 发布:在香港用淘宝 编辑:程序博客网 时间:2024/05/29 03:29



一.Tip:上传文件的处理细节

1.中文文件乱码问题
文件名中文乱码问题,可调用ServletUpLoadersetHeaderEncoding方法,或者设置request的setCharacterEncoding属性

普通字段的乱码
  1.手工转换
  2.FileItem.getString("UTF-8");获得名称的时候传一个字符集
 上传文件的乱码: ServletFileUpload.setHeaderEncoding("UTF-8");


2.临时文件的删除问题
由于文件大小超出DiskFileItemFactory.setSizeThreshold方法设置的内存缓冲区的大小时,Commons-fileupload组件将使用临时文件保存上传数据,因此在程序结束时,务必调用FileItem.delete方法删除临时文件。

在处理完每一个item之后,要记得调用item.delete方法,删除临时文件
Delete方法的调用必须位于流关闭之后,否则会出现文件占用,而导致删除失败的情况。


3.文件存放位置
为保证服务器安全,上传文件应保存在应用程序的WEB-INF目录下,或者不受WEB服务器管理的目录。
为防止多用户上传相同文件名的文件,而导致文件覆盖的情况发生,文件上传程序应保证上传文件具有唯一文件名。
为防止单个目录下文件过多,影响文件读写速度,处理上传文件的程序应根据可能的文件上传总量,选择合适的目录结构生成算法,将上传文件分散存储。

 

4.如何处理空文件上传
 在处理item时,判断item的getName方法返回的是不是"",如果为空,则代表客户机没有上传文件

 

5.限制上传文件的最大值
 限制单个的最大值:upload.setFileSizeMax(1024*1024);   FileUploadBase.FileSizeLimitExceededException
 限制多个的最大值:upload.setSizeMax(1024*1024*5);  FileUploadBase.SizeLimitExceededException

 

6.为防止多用户上传相同文件名的文件,而导致文件覆盖的情况发生,文件上传程序应保证上传文件具有唯一文件名。
 public String generateFilename(String filename){
  return UUID.randomUUID().toString() + "_" + filename;  //83743_9834834_9u34_9834-1.avi
 }

 

7.为避免在一个目录保存多个文件,影响文件读取的性能,应把文件打散到多个目录存储
 public String generateFilepath(String uploadpath,String filename){  //upload
  
  int hashcode = filename.hashCode();
  int dir1 = hashcode&0xf;
  int dir2 = (hashcode>>4)&0xf;
  //  http://  c:\\
  String savepath = uploadpath + "\" + dir1 + "\" + dir2;
  File file = new File(savepath);
  if(!file.exists()){
   file.mkdirs();
  }
  return savepath;
 }

 

8.限制上传文件的类型
 得到上传文件的后缀名,判断是否合法,如果不合法,则抛异常提醒用户


9.ProgressListener显示上传进度
ProgressListener progressListener = new ProgressListener() {
 public void update(long pBytesRead, long pContentLength, int pItems) {

 System.out.println("到现在为止,  " + pBytesRead + " 字节已上传,总大小为 "
     + pContentLength);
 }
};
upload.setProgressListener(progressListener);
以KB为单位显示上传进度
long temp = -1;   //temp注意设置为类变量
long ctemp = pBytesRead /1024;
if (mBytes == ctemp) 
 return;
temp = mBytes;

 

10.做出动态上传效果

 

实例

public class UploadServlet4 extends HttpServlet {

 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  
  //request.setCharacterEncoding("UTF-8");这个解决不了上传文件的乱码问题
  List exts = Arrays.asList("jpg","bmp"); //创建一个集合,封装限制上传文件类型数据
  try{
   //1.创建工厂
   DiskFileItemFactory factory = new DiskFileItemFactory();
   //设置缓冲文件夹路径
   factory.setRepository(new File(this.getServletContext().getRealPath("/temp")));
   
   //2.得到解析器
   ServletFileUpload upload = new ServletFileUpload(factory);
   //设置解析器的字符集
   upload.setHeaderEncoding("UTF-8");
   //设置单个上传文件最大容量
   upload.setFileSizeMax(1024*1024);
   //设置多个上传文件最大容量
   upload.setSizeMax(1024*1024*5);
   //设置监听器,创建一个接口,实现接口方法,从监听器中获得:上传文件的当前上传字节pBytesRead,上传文件总大小pContentLength,正在处理的上传对象pItems
   upload.setProgressListener(new ProgressListener(){
    public void update(long pBytesRead, long pContentLength, int pItems) {
     System.out.println("当前处理的是" + pItems + "上传文件,文件大小是: " + pContentLength + ",当前已上传:" + pBytesRead + "字节");
    }
   });
   
   //3.用解析器解析request,得到代表每一个输入项的fileitem对象
   List<FileItem> list = upload.parseRequest(request);
   
   //4.迭代集合,获取每一个fileitem的数据
   for(FileItem item : list){
    if(item.isFormField()){
     //代表当前获取的普通输入项的数据
     String inputName = item.getFieldName();  //username
     String inputValue = item.getString("UTF-8"); //在获得上传数据时通过参数直接给字符集相当于下面代码
     //inputValue = new String(inputValue.getBytes("iso8859-1"),"UTF-8");
     System.out.println(inputName + "=" + inputValue);
    }else{  //代表当前获取的item封装的是上传文件的数据
     //获得上传文件的文件路径
     String filename = item.getName();  //""
     //判断上传文件路径为空的情况
     if(filename.trim().equals("")){
      continue;
     }
     //根据上传文件名获得文件类型,判断exts集合中是否允许该类型上传,如果不支持,抛一个自定义异常
     String ext = filename.substring(filename.lastIndexOf(".")+1);
     if(!exts.contains(ext)){  //集合的是否包含方法
      throw new ExtException();
     }
     //如果支持,获得文件名
     filename = filename.substring(filename.lastIndexOf("\")+1);  //""
     
     //获得上传对象的输入流读取文件输出到指定位置
     InputStream in = item.getInputStream();
     int len = 0;
     byte buffer[] = new byte[1024];
     //输出路径
     String uploadpath = this.getServletContext().getRealPath("/WEB-INF/upload");
     //传入文件名返回一个随即生成带ID的唯一保存文件名
     String saveFilename = generateFilename(filename);
     //传入输出路径和保存文件名,根据hash算法创建目录,返回一个用于将传入文件打散保存的保存路径
     String savePath = generateFilepath(uploadpath, saveFilename);
     //创建输出流到指定保存地址
     FileOutputStream out = new FileOutputStream(savePath + "\" + saveFilename);
     while((len=in.read(buffer))>0){
      out.write(buffer, 0, len);
     }
     
     in.close();
     out.close();
     item.delete();  //删除item对应的临时文件
     
    }
   }
   request.setAttribute("message", "上传成功!!");
  }catch (FileUploadBase.FileSizeLimitExceededException e) {
   request.setAttribute("message", "上传文件不能超过1M");
  }catch (FileUploadBase.SizeLimitExceededException e) {
   request.setAttribute("message", "上传文件的大小加起来不能超过5M");
  }catch (ExtException e) {
   request.setAttribute("message", "上传文件只能是jpg,bmp");
  }catch (Exception e) {
   e.printStackTrace();
   request.setAttribute("message", "由于未知错误上传失败!!");
  }
  request.getRequestDispatcher("/message.jsp").forward(request, response);
 }

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

 //需要的更具类方法,本应该写在工具类中,这里为了方便直接写在servlet里


 //根据传入的文件名生成一个带ID的唯一的文件名返回
 public String generateFilename(String filename){
  return UUID.randomUUID().toString() + "_" + filename;  //83743_9834834_9u34_9834-1.avi
 }


 //获得打散保存路径方法
 public String generateFilepath(String uploadpath,String filename){  //upload
  //根据传进来的文件名算出hash值
  int hashcode = filename.hashCode();
  //获得hash值的后4位的int数作为1级保存目录
  int dir1 = hashcode&0xf;
  //将hash值右移4位,也就是获取5到8位,作为2级保存目录
  int dir2 = (hashcode>>4)&0xf;
  //  http://  c:\\  根据级目录组合成一个为文件保存的目录
  String savepath = uploadpath + "\" + dir1 + "\" + dir2;
  //创建文件流,将保存地址传入,如果不存在则创建其所有目录,最后返回该目录地址
  File file = new File(savepath);
  if(!file.exists()){
   file.mkdirs();
  }
  return savepath;
 }

}

 

JSP编写动态上传效果

<%@ page language="Java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>动态上传</title>
   
    <script type="text/JavaScript">
     function add(){
      
      var input = document.create_rElement("input");
      input.type = "file";
      input.name = "file";
      
      var btn = document.create_rElement("input");
      btn.type = "button";
      btn.value = "删除";
      btn.onclick = function del(){

    <!--获得这个节点的父节点的父节点,删除其孩子节点(这个节点的父节点),这样就删除了整个DIV-->
       this.parentNode.parentNode.removeChild(this.parentNode);
      }
      
      var div = document.create_rElement("div");
      div.a(input);
      div.a(btn);
      
      document.getElementByIdx_x("files").a(div);
     }
    </script>
  </head>
 
  <body>
   
    <form action="${pageContext.request.contextPath }/servlet/UploadServlet4" method="post" enctype="multipart/form-data">
     <table>
      <tr>
       <td>上传用户:</td>
       <td>
        <input type="text" name="username">
       </td>
      </tr>
      
      <tr>
       <td></td>
       <td>
        <input type="button" value="添加文件" onclick="add()">
       </td>
      </tr>
      
      <tr>
       <td></td>
       <td>
        <div id="files">
        
        </div>
       </td>
      </tr>
      <tr>
       <td></td>
       <td>
        <input type="submit" value="上传">
       </td>
      </tr>
     </table>
    </form>
   
  </body>
</html>

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 6s开机密码忘了怎么办 苹果手机忘记解锁密码怎么办 忘记苹果触控id怎么办 苹果6app被锁了怎么办 捡的苹果id锁了怎么办 苹果手机id密码锁了怎么办 美版5s刷机后激活怎么办 vivo手机图案解锁忘记了怎么办 苹果5sid锁死了怎么办 苹果id账号被锁怎么办 苹果6s忘了ld怎么办 小米忘记图形解锁怎么办呢 索尼手机忘记解锁图案怎么办 oppoa37忘记锁屏密码怎么办 oppoa37锁屏密码忘了怎么办 oppor9图案密码忘了怎么办 oppor忘记锁屏图案怎么办 oppor手机忘记解锁图案怎么办 oppor手机忘记图案了怎么办 oppo手机屏幕锁忘了怎么办 三星手机屏幕锁忘了怎么办 手机主菜单坏了怎么办 索尼手机密码忘了怎么办 索尼笔记本密码忘了怎么办 索尼手机解锁密码忘了怎么办 索尼记录仪密码忘了怎么办 索尼z3手机忘记开机密码怎么办 索尼忘记锁屏密码怎么办 索尼手机忘记锁屏密码怎么办 忘了手机解锁图案怎么办 索尼手机忘记开机密码怎么办 索尼笔记本开机密码忘了怎么办 手机的开机密码忘了怎么办 联想手机开机密码忘了怎么办 红米note3忘记开机密码怎么办 小米2忘了密码怎么办 小米笔记本电脑忘记开机密码怎么办 小米笔记本忘记开机密码怎么办 小米手机儿童模式忘记密码怎么办 小米应用锁密码忘了怎么办 小米air密码忘了怎么办