jsp WebUploader 分块上传
2021-02-14 10:21
                         标签:本地   rate   mysql   stream   inf   配置   三方   img   客户端    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小限制,post没有) 2.表单的enctype属性:必须设置为multipart/form-data. 3.表单必须有文件上传项:file,且文件项需要给定name值 上传文件夹需要增加一个属性webkitdirectory,像这样: 不过webkitdirectory属性有个问题,只能支持高版本的chrome,不能支持低版本的IE,如ie6,ie7,ie8,不能做到全浏览器适配,运行环境比较单一。 js中可以判断文件夹中文件数量及文件夹大小是否符合要求,不符合要求不能向后台提交: 前台HTML模板 this.GetHtmlFiles = function() {      var acx = "";      acx += ‘                                                                                                                                                                                                                                                                                                           \                        \                        \                          acx += ‘      //文件夹模板      acx += ‘                                                                                                                                                                                                                                                                                                              \                        \                        \                          acx += ‘      //上传列表      acx += ‘                                                                                                                             return acx; }; 选择文件,选择文件夹,粘贴文件和文件夹的逻辑 this.open_files = function (json) {      for (var i = 0, l = json.files.length; i 
     {          this.addFileLoc(json.files[i]);      }      setTimeout(function () { _this.PostFirst(); },500); }; this.open_folders = function (json) {     for (var i = 0, l = json.folders.length; i 
         this.addFolderLoc(json.folders[i]);     }      setTimeout(function () { _this.PostFirst(); }, 500); }; this.paste_files = function (json) {      for (var i = 0, l = json.files.length; i 
      {          this.addFileLoc(json.files[i]);      } }; 后台在接收文件夹时不同之处在需要用MultipartHttpServletRequest boolean isMultipart = ServletFileUpload.isMultipartContent(request); FileItemFactory factory = new DiskFileItemFactory();   ServletFileUpload upload = new ServletFileUpload(factory); List files = null; try {      files = upload.parseRequest(request); } catch (FileUploadException e) {// 解析文件数据错误      out.println("read file data error:" + e.toString());     return;    }   FileItem rangeFile = null; // 得到所有上传的文件 Iterator fileItr = files.iterator(); // 循环处理所有文件 while (fileItr.hasNext()) {      // 得到当前文件      rangeFile = (FileItem) fileItr.next();      if(StringUtils.equals( rangeFile.getFieldName(),"pathSvr"))      {          pathSvr = rangeFile.getString();          pathSvr = PathTool.url_decode(pathSvr);      } }   server端的包和类   文件块处页面,验证代码部分 boolean verify = false; String msg = ""; String md5Svr = ""; long blockSizeSvr = rangeFile.getSize(); if(!StringUtils.isBlank(blockMd5)) {      md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream()); }   verify = Integer.parseInt(blockSize) == blockSizeSvr; if(!verify) {      msg = "block size error sizeSvr:" + blockSizeSvr + "sizeLoc:" + blockSize; }   if(verify && !StringUtils.isBlank(blockMd5)) {      verify = md5Svr.equals(blockMd5);      if(!verify) msg = "block md5 error"; }   if(verify) {      //保存文件块数据      FileBlockWriter res = new FileBlockWriter();      //仅第一块创建      if( Integer.parseInt(blockIndex)==1) res.CreateFile(pathSvr,Long.parseLong(lenLoc));      res.write( Long.parseLong(blockOffset),pathSvr,rangeFile);      up6_biz_event.file_post_block(id,Integer.parseInt(blockIndex));           JSONObject o = new JSONObject();      o.put("msg", "ok");      o.put("md5", md5Svr);       o.put("offset", blockOffset);//基于文件的块偏移位置      msg = o.toString(); } rangeFile.delete(); out.write(msg);   生成文件名称的逻辑 public String genFile(int uid, String md5,String nameLoc) throws IOException {      SimpleDateFormat fmtDD = new SimpleDateFormat("dd");      SimpleDateFormat fmtMM = new SimpleDateFormat("MM");      SimpleDateFormat fmtYY = new SimpleDateFormat("yyyy");           Date date = new Date();      String strDD = fmtDD.format(date);      String strMM = fmtMM.format(date);      String strYY = fmtYY.format(date);           String path = this.getRoot() + "/";      path = path.concat(strYY);      path = path.concat("/");      path = path.concat(strMM);      path = path.concat("/");      path = path.concat(strDD);      path = path.concat("/");      path = path.concat(md5);      path = path.concat(".");      path = path.concat(PathTool.getExtention(nameLoc));                    File fl = new File(path);           return fl.getCanonicalPath();// }   以下是service层做的处理: 整体模块划分如下: 其中数据类实体逻辑处理如下 public class FileInf {        public FileInf(){}      public String id="";      public String pid="";     public String pidRoot="";         /**  * 表示当前项是否是一个文件夹项。    */      public boolean fdTask=false;              //   /// 是否是文件夹中的子文件  ///       public boolean fdChild=false;      /**  * 用户ID。与第三方系统整合使用。    */      public int uid=0;      /**  * 文件在本地电脑中的名称   */      public String nameLoc="";      /**  * 文件在服务器中的名称。   */      public String nameSvr="";      /**  * 文件在本地电脑中的完整路径。示例:D:\Soft\QQ2012.exe */      public String pathLoc="";        /**  * 文件在服务器中的完整路径。示例:F:\\ftp\\uer\\md5.exe     */      public String pathSvr="";      /**  * 文件在服务器中的相对路径。示例:/www/web/upload/md5.exe   */      public String pathRel="";      /**  * 文件MD5    */      public String md5="";      /**  * 数字化的文件长度。以字节为单位,示例:120125    */      public long lenLoc=0;      /**  * 格式化的文件尺寸。示例:10.03MB   */      public String sizeLoc="";      /**  * 文件续传位置。  */      public long offset=0;      /**  * 已上传大小。以字节为单位 */      public long lenSvr=0;      /**  * 已上传百分比。示例:10%  */      public String perSvr="0%";      public boolean complete=false;      public Date PostedTime = new Date();      public boolean deleted=false;      /**  * 是否已经扫描完毕,提供给大型文件夹使用,大型文件夹上传完毕后开始扫描。  */      public boolean scaned=false; } 后台数据库中的逻辑基本上都用到了上面的实体类 文件数据表操作类如下 加载所有未完成的文件列表 public String GetAllUnComplete(int f_uid) {      StringBuilder sb = new StringBuilder();      sb.append("select ");      sb.append(" f_id");      sb.append(",f_fdTask");          sb.append(",f_nameLoc");      sb.append(",f_pathLoc");      sb.append(",f_md5");      sb.append(",f_lenLoc");      sb.append(",f_sizeLoc");      sb.append(",f_pos");      sb.append(",f_lenSvr");      sb.append(",f_perSvr");      sb.append(",f_complete");      sb.append(",f_pathSvr");//fix(2015-03-16):修复无法续传文件的问题。      sb.append(" from up6_files ");//change(2015-03-18):联合查询文件夹数据      sb.append(" where f_uid=? and f_deleted=0 and f_fdChild=0 and f_complete=0 and f_scan=0");//fix(2015-03-18):只加载未完成列表        ArrayList      DbHelper db = new DbHelper();      PreparedStatement cmd = db.GetCommand(sb.toString());      try {          cmd.setInt(1, f_uid);          ResultSet r = db.ExecuteDataSet(cmd);          while(r.next())          {               FileInf f          = new FileInf();               f.uid              = f_uid;               f.id               = r.getString(1);               f.fdTask      = r.getBoolean(2);                             f.nameLoc          = r.getString(3);               f.pathLoc          = r.getString(4);               f.md5              = r.getString(5);               f.lenLoc      = r.getLong(6);               f.sizeLoc          = r.getString(7);               f.offset      = r.getLong(8);               f.lenSvr      = r.getLong(9);               f.perSvr      = r.getString(10);               f.complete         = r.getBoolean(11);               f.pathSvr     = r.getString(12);//fix(2015-03-19):修复无法续传文件的问题。               files.add(f);                        }          r.close();          cmd.getConnection().close();          cmd.close();      } catch (SQLException e) {          // TODO Auto-generated catch block          e.printStackTrace();      }           if(files.size() 
           Gson g = new Gson();     return g.toJson( files);//bug:arrFiles为空时,此行代码有异常 } 实现后的整体效果如下 文件夹上传完后的效果 服务器保存的文件夹数据,而且层级结构与本地客户端是一致的。这在OA系统中,或者网盘系统中使用时是非常有用的 后端代码逻辑大部分是相同的,目前能够支持MySQL,Oracle,SQL。在使用前需要配置一下数据库,可以参考我写的这篇文章:http://blog.ncmem.com/wordpress/2019/08/12/java-http%E5%A4%A7%E6%96%87%E4%BB%B6%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0%E4%B8%8A%E4%BC%A0/ 欢迎入群一起讨论“374992201” jsp WebUploader 分块上传 标签:本地   rate   mysql   stream   inf   配置   三方   img   客户端    原文地址:https://www.cnblogs.com/songsu/p/12992610.html



 
  
  
  
  
 
上一篇:时间技巧js

