Implementation technology of uploading and downloading JSP large files (above 10G)

What we usually do is upload files. The upload folder is similar to the upload file, but there are some differences. This time we made the upload folder and record it for later use.

The first thing we need to understand is the three elements of uploading files:

1. Form submission method: post (get method submission has a size limit, post does not)

2. The enctype attribute of the form: must be set to multipart/form-data.

3. The form must have a file upload item: file, and the file item needs to be given a name value

The upload folder needs to add an attribute webkitdirectory, like this:

<input id="fileFolder" name="fileFolder" type="file"  webkitdirectory>

However, there is a problem with the webkitdirectory attribute. It can only support high versions of chrome, and cannot support low versions of IE, such as ie6, ie7, and ie8. It cannot be adapted to all browsers and the operating environment is relatively single.

In js, you can judge whether the number of files in the folder and the size of the folder meet the requirements, and you cannot submit to the background if they do not meet the requirements:

Front HTML template

this.GetHtmlFiles = function()

{

     var acx = "";

     acx += '<div class="file-item" id="tmpFile" name="fileItem">\

                <div class="img-box"><img name="file" src="js/file.png"/></div>\

                   <div class="area-l">\

                       <div class="file-head">\

                            <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\

                            <div name="percent" class="percent">(35%)</div>\

                            <div name="fileSize" class="size" child="1">1000.23MB</div>\

                    </div>\

                       <div class="process-border"><div name="process" class="process"></div></div>\

                       <div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\

                   </div>\

                   <div class="area-r">\

                    <span class="btn-box" name="cancel" title="取消"><img name="stop" src="js/stop.png"/><div>取消</div></span>\

                    <span class="btn-box hide" name="post" title="继续"><img name="post" src="js/post.png"/><div>继续</div></span>\

                       <span class="btn-box hide" name="stop" title="停止"><img name="stop" src="js/stop.png"/><div>停止</div></span>\

                       <span class="btn-box hide" name="del" title="删除"><img name="del" src="js/del.png"/><div>删除</div></span>\

                   </div>';

     acx += '</div>';

     //Folder template

     acx += '<div class="file-item" name="folderItem">\

                   <div class="img-box"><img name="folder" src="js/folder.png"/></div>\

                   <div class="area-l">\

                       <div class="file-head">\

                            <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\

                            <div name="percent" class="percent">(35%)</div>\

                            <div name="fileSize" class="size" child="1">1000.23MB</div>\

                    </div>\

                       <div class="process-border top-space"><div name="process" class="process"></div></div>\

                       <div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\

                   </div>\

                   <div class="area-r">\

                    <span class="btn-box" name="cancel" title="取消"><img name="stop" src="js/stop.png"/><div>取消</div></span>\

                    <span class="btn-box hide" name="post" title="继续"><img name="post" src="js/post.png"/><div>继续</div></span>\

                       <span class="btn-box hide" name="stop" title="停止"><img name="stop" src="js/stop.png"/><div>停止</div></span>\

                       <span class="btn-box hide" name="del" title="删除"><img name="del" src="js/del.png"/><div>删除</div></span>\

                   </div>';

     acx += '</div>';

     //Upload list

     acx += '<div class="files-panel" name="post_panel">\

                   <div name="post_head" class="toolbar">\

                       <span class="btn" name="btnAddFiles">Select multiple files</span>\

                       <span class="btn" name="btnAddFolder">Select a folder</span>\

                       <span class="btn" name="btnPasteFile">Paste files and directories</span>\

                       <span class="btn" name="btnSetup">安装控件</span>\

                   </div>\

                   <div class="content" name="post_content">\

                       <div name="post_body" class="file-post-view"></div>\

                   </div>\

                   <div class="footer" name="post_footer">\

                       <span class="btn-footer" name="btnClear">Clear completed files</span>\

                   </div>\

              </div>';

     return acx;

};

The logic of selecting files, selecting folders, pasting files and folders

this.open_files = function (json)

{

     for (var i = 0, l = json.files.length; i < l; ++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 < l; ++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 < l; ++i)

     {

         this.addFileLoc(json.files[i]);

     }

};

The difference when receiving folders in the background is that MultipartHttpServletRequest is needed

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)

{// Parsing file data error 

    out.println("read file data error:" + e.toString());

    return;

  

}

 

FileItem rangeFile = null;

// Get all uploaded files

Iterator fileItr = files.iterator();

// Loop through all files

while (fileItr.hasNext())

{

     // Get the current file

     rangeFile = (FileItem) fileItr.next();

     if(StringUtils.equals( rangeFile.getFieldName(),"pathSvr"))

     {

         pathSvr = rangeFile.getString();

         pathSvr = PathTool.url_decode(pathSvr);

     }

}

 

Packages and classes on the server side

 

Page at the file block, verify the code part

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)

{

     //Save file block data

     FileBlockWriter res = new FileBlockWriter();

     //Create only the first block

     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);//file-based block offset position

     msg = o.toString();

}

rangeFile.delete();

out.write(msg);

 

The logic of generating file names

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();//

}

 

The following is the processing done by the service layer:

The overall module is divided as follows:

The data type entity logic is processed as follows

public class FileInf {

 

     public FileInf(){}

     public String id="";

     public String pid="";

    public String pidRoot="";   

     /** * Indicates whether the current item is a folder item. */

     public boolean fdTask=false;        

     // /// Is it a sub-file in the folder /// </summary>

     public boolean fdChild=false;

     /** * User ID. Integrated with third-party systems. */

     public int uid=0;

     /** * The name of the file on the local computer */

     public String nameLoc="";

     /** * The name of the file on the server. */

     public String nameSvr="";

     /** * The full path of the file on the local computer. Example: D:\Soft\QQ2012.exe */

     public String pathLoc="";  

     /** * The full path of the file on the server. Example: F:\\ftp\\uer\\md5.exe */

     public String pathSvr="";

     /** * The relative path of the file on the server. Example: /www/web/upload/md5.exe */

     public String pathRel="";

     /** * File MD5 */

     public String md5="";

     /** * The length of the digitized file. In bytes, for example: 120125 */

     public long lenLoc=0;

     /** * Formatted file size. Example: 10.03MB */

     public String sizeLoc="";

     /** * File resume location. */

     public long offset=0;

     /** * The size has been uploaded. In bytes */

     public long lenSvr=0;

     /** * Percentage uploaded. Example: 10% */

     public String perSvr="0%";

     public boolean complete=false;

     public Date PostedTime = new Date();

     public boolean deleted=false;

     /** * Whether the scan has been completed, and it is provided to large folders. Scanning will start after the large folders are uploaded. */

     public boolean scaned=false;

}

The logic in the backend database basically uses the above entity classes

The file data table operation class is as follows

Load a list of all outstanding files

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): Fix the problem that the file cannot be resumed.

     sb.append(" from up6_files ");//change(2015-03-18): joint query folder data

     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): load only the unfinished list

 

     ArrayList<FileInf> files = new ArrayList<FileInf>();

     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): Fix the problem that the file cannot be resumed.

              files.add(f);

             

         }

         r.close();

         cmd.getConnection().close();

         cmd.close();

     } catch (SQLException e) {

         // TODO Auto-generated catch block

         e.printStackTrace ();

     }

    

     if(files.size() < 1) return null;

    

     Gson g = new Gson ();

    return g.toJson( files);//bug: When arrFiles is empty, this line of code is abnormal

}

The overall effect after implementation is as follows

Effect after uploading the folder

The folder data saved by the server, and the hierarchical structure is consistent with that of the local client. This is very useful when used in an OA system or a network disk system

Most of the back-end code logic is the same, and it currently supports MySQL, Oracle, and SQL. You need to configure the database before use, you can refer to this article I wrote: 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/

Welcome to join the group to discuss "374992201"

Guess you like

Origin blog.csdn.net/weixin_45525177/article/details/108509594