fileUpload

文件上传

文件上传

  • 文件上传的概念:
    • 什么是文件上传,将本地的文件,通过流,写入到服务器上。
  • 文件上传的技术
    • jspSmartUpload:应用在jsp中的文件上传和下载的组建。(应用在Model1年代)
    • fileUpload : Apache下的一个子项目,在java的环境下实现文件的上传
    • Servlet3.0 : 注解开发,文件上传(API不全 ),异步请求
    • struts2 : 支持文件上传(底层FileUpload)
  • 文件上传的要素:

    • 表单提交的方式是post(get有大小限制)
    • 表单中必须有文件上传项,而且必须要有name属性跟值。<input type="file" name="upload">
    • 表单中必须要有enctype属性值为multipart/form-data要不拿不到文件内容
      • enctype有默认值为application/x-www-form-urlencoded如果不改的话,上传文件的时候只能上传文件名
      • enctype属性值为multipart/form-data时就不能用getParameter();来获得属性了要用String name =fileItem.getFiledName();来获得名字,用String value=fileItem.getString("编码方式");获得值
  • 文件上传的原理分析

  • FileUpload文件上传的步骤分析

1.创建一个磁盘文件项工厂
DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory();
2.创建核心解析类
ServletFileUpload servletFileUpload=new ServletFileUpload(diskFileItemFactory);
3.解析request,返回List集合
List<FileItem> list = servletFileUpload.parseRequest(request);
4.遍历集合获得每个部分的内容,获得每个部分,如果是文件上传项,完成文件上传工作操作。
for(FileItem fileItem:list){
   //4.1判断是否是普通项
   if(fileItem.isFileField()){
      //普通项
      //接受到普通项的名字跟值
      String name =fileItem.getFiledName();
      String value=fileItem.getString();
   }else{
      //文件项
      //获得文件名跟输入流
      String fileName=fileItem.getName();
      InputStream is=fileItem.getInputStream();
      //获得文件上传的路径:
      String path =this.getServletContext.getRealPath("/upload");
      OutputStream os=new FileOutputStream(path + "/"+fileName);
      //两个流对接
      int len =0;
      byte[] b=new byte[1024];
      while((len=is.read(b))!=-1){
         os.write(b,0,len);
      }
      is.close();
      os.close();
   }
   //删除临时文件
   fileItem.delete();
}

FileUpload中API

  • DiskFileItemFactory:磁盘文件项工厂
//设置缓冲区的大小3M
diskFileItemFactory.setSizeThreshold(3*1024*1024);
//设置临时文件存放的路径(比缓冲区大才会生成临时文件)
String path=this.getServletContext.getRealPath("/temp");
diskFileItemFactory.setRepository(new File(path));
  • ServletFileUpload

    • 判断表单中的enctype属性是否是multipart/form-data
      01

    • 解析 request
      02

    • 设置中文文件名乱码
      03

    • 设置上传的当个文件大小

      • public void setFileSizeMax(long fileSizeMax)
    • 设置上传的总文件大小

      • public void setSizeMax(long sizeMax)
  • FileItem

    • 判断是普通项还是文件上传项

      • boolean isFormField()
    • 普通项(获得普通项名)

      • String getFieldName()
    • 普通项(获得普通项的值)

      • String getString()
        String getString(String encoding)
    • 上传项(获得文件名)

      • String getName()
    • 上传项(获得文件输入流)

      • InputStream getInputStream()
    • 删除临时文件
      • void delete()

文件上传的问题解决

  • 文件名路径重名(老版本的浏览器带文件名路径)
int id=fileName.lastIndexOf("/");
if(id!= -1){
   //说明文件名中不包含路径
   fileName=fileName.substring(id+1);
}
  • 文件名重名(可以封装成一个工具类)
int idx=fileName.laseIndexOf(".");
String extetion=fileName.substring(idx); String newFileName=UUID.randomUUID().toString().replace("-","")+extetion;
  • 一个目录下存放的文件过多(目录分离)
    • 按时间分离:一个星期一个目录
    • 按用户分离:一个用户一个目录
    • 按个数分离:一个目录下放300个
    • 按算法分离:按照特定的目录分离算法进行分离
//算法分离(工具类中)
//获得唯一文件名的hashcode值
int code1=uuidFileName.hashCode();
//让这个值&0xf 到一个一级目录
int d1=code1 & 0xf;
//让hashcode值右移4位
int code2=code1>>>4;
int d2 = code2 & 0xf; //作为2级目录
return "/"+d1+"/"+d2;

以此类推可以得到最多8级目录,每级中有16个不同的值。
使用这个工具类时如下:
05

注:

在文件上传的时候因为form表单中的enctype属性值为mulipart/form-data时就不能用getParameter()了,所以就不能继承basicServlet了,要单独自己写一个servlet

Struts中的文件上传

  • Struts2中实现文件上传的基本的功能:
    • 在Struts2中实现文件上传是通过拦截器实现的
    • 提供三个对象的属性即可:
      • 上传的文件名:表单上传的名称+FileName. private String uploadFileName;
      • 上传的文件类型:表单上传名称+ContentType. private String uploadContentType;
      • 上传的文件 文件类型的表单上传项。 private Fileupload.
//实现文件上传,首先提供这三个属性
private String uploadFileName;
private String uploadContentType;
private File upload;
//记得要提供set方法

//在指定的方法中实现文件上传
private String uploadAction(){
   //判断是否选中文件
   if(upload != null){
       //文件上传的路劲
       String realPath=".....";
       //可以获得唯一文件名
       String uuidFileName = UploadUtils.getUUIDFileName(uploadFileName);
       //获得目录分离的路劲
       String path = UploadUtils.getPath(uuidFileName);
       File file = new File (realPath + path);
       if(!file.exists()){
           file.mkdirs();
       }
       //创建一个文件目录
       String str=readPath+path+"/"+uuidFileName;
       File dickFile = new File (str);
       //实现文件上传
       FileUtils.copyFile(upload,dickFile);
   }
   return "saveSuccess";
}

  • 文件上传的参数都在 default.properties 中呢
  • 有的则需要在拦截器中设置
//设置拦截器需要在配置文件中<action>标签中设置
<interceptor-ref name="defaultStack">
    <!-- 数据的最大值 -->
    <param name="fileUpload.maximumSize">1048576</param>
    <!-- 后缀名 -->
    <param name="fileUpload.allows">.jpg</param>
</interceptor-ref>
  • 还需要在配置文件中设置input标签,如果上传内容与拦截器中规定的不同会走Input标签
    • 还能再input返回的页面设置<s:fielderror/>显示上传的错误信息

uploadUtils

import java.util.UUID;
/**
 * 文件上传的工具类
 * @author zc
 *
 */
public class UploadUtils {

    /**
     * 获得唯一文件名的方法:
     * @param fileName
     * @return
     */
    public static String getUUIDFileName(String fileName){
        // aaa.txt   --- sdklflsdf.txt 
        int idx = fileName.lastIndexOf(".");
        String extetion = fileName.substring(idx);
        return UUID.randomUUID().toString().replace("-", "")+extetion;
    }

    /**
     * 获得分录分录的路径:
     * @param args
     */
    public static String getPath(String uuidFileName){
        // 获得唯一文件名的hashCode值。
        int code1 = uuidFileName.hashCode();
        // 让这个值&0xf 得到一个一级目录。
        int d1 = code1 & 0xf;// 作为1级目录.
        // 让hashCode值右移4位:
        int code2 = code1 >>> 4;
        int d2 = code2 & 0xf; // 作为2级目录.
        return "/"+d1+"/"+d2;
    }

    public static void main(String[] args) {
        System.out.println("986a6146e9104e00838c123bcc371cd3.txt".hashCode());
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值