JSP front-end large file uploads

We usually always do is upload files, folders and upload files to upload similar, but there are some differences, this did upload folder on the record for future use after the next.

The project needs:

Support for large files and upload resume, resume required to support all browsers, including ie6, ie7, ie8, ie9, Chrome, Firefox, 360 security browser and refresh the browser still be able to resume, restart your browser (close your browser and open) can still continue to upload, you restart the computer and still be able to upload

Supports folder upload, requires the server to retain a hierarchical structure, and can resume. The need to support more than 100,000 folder upload.

Support low version of the system and the browser, because the project's final operating environment in the government, the government of configurations in general, are office staff, memory is not large, basically a Windows XP-based system.

 

1. Introduction enctype

Enctype attribute specifies how it should be encoded form data before sending it to the server.

enctype function is to inform the server request body MIME type (action request message as the content-type header)

1,1 enctype value of three

value

description

application/x-www-form-urlencoded

Coding all the characters (default) before sending

multipart/form-data

Not the character encoding. Each table is divided into a single component

text/plain

Spaces converted to "+" plus, but not a special character encoding.

1. 当enctype=’application/x-www-form-urlencoded’

2.当enctype=’multipart/form-data’

 

The observation that the body of the request to change. Such a request is called a multi-member body in the request body.

What is a multi-part request body: each table is to be divided into a single member.

In the latter boundary content-type of the request header is a string of random string as the division identifier

Ordinary Form Item:

// name mean value of the name attribute inside a text box, and the value of our admin text input

Content-Disposition: form-data; name="username"

admin

File Form Item

// filename means: We upload the file name, content-Type means: MIME type, asdasdas means: the contents of a file inside

Content-Disposition: form-data; name="upload"; filename="a.txt"

Content-Type: text/plain

asdasdas

3. 当enctype=’text/plain’

 

w3c said: Spaces will become "+" plus sign, but I did not find here, get only when requested, the space will become a "+" sign

 

Into the title

Complete the upload need to meet three necessary conditions

Provided form the form, method must be post, because the transmission of data get request is generally 2kb, different browsers is not the same.

Form Properties form must be enctype multipart / form-data

Upload input field to provide input type = "file" category

The principle generally: When the values ​​are enctype multipart / form-data, the browser will each table item is divided, is divided into different parts, is divided at the boundary identification, the identification string is randomly generated Finally, at the end of a divided identification string form item will be two more "- -" represents the end. Get string dividing server request.getHeader ( "content-type"), and then parsed.

 

 

Code

First, the development environment to build

Prepare two third-party jar package

commons-io package

commons-upload package

All dependencies

 

Code

<%@ page language="java" import="up6.DBFile" pageEncoding="UTF-8"%>

<%@ page contentType="text/html;charset=UTF-8"%>

<%@ page import="up6.FileBlockWriter" %>

<%@ page import="up6.XDebug" %>

<%@ page import="up6.*" %>

<%@ page import="up6.biz.*" %>

<%@ page import="org.apache.commons.fileupload.FileItem" %>

<%@ page import="org.apache.commons.fileupload.FileItemFactory" %>

<%@ page import="org.apache.commons.fileupload.FileUploadException" %>

<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory" %>

<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload" %>

<%@ page import="org.apache.commons.lang.*" %>

<%@ page import="java.net.URLDecoder"%>

<%@ page import="java.util.Iterator"%>

<%@ page import="net.sf.json.JSONObject"%>

<%@ page import="java.util.List"%>

<%

out.clear();

String uid             = request.getHeader("uid");//

String id              = request.getHeader("id");

String lenSvr      = request.getHeader("lenSvr");

String lenLoc      = request.getHeader("lenLoc");

String blockOffset = request.getHeader("blockOffset");

String blockSize   = request.getHeader("blockSize");

String blockIndex  = request.getHeader("blockIndex");

String blockMd5        = request.getHeader("blockMd5");

String complete        = request.getHeader("complete");

String pathSvr         = "";

 

// parameter is empty

if(  StringUtils.isBlank( uid )

     || StringUtils.isBlank( id )

     || StringUtils.isBlank( blockOffset ))

{

     XDebug.Output("param is null");return;

}

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

     }

}

 

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

%>

Download a necessary condition

A first two streams

content-type

Content-Type is very important to return the message content, represents the content of the document belongs to what MIME type.

The browser will decide how to display the returned message body content based on Content-Type.

The default value is text / html

You can use request.getServletContext (). GetMimeType ( "filename") to obtain the MIME type.

Content-Disposition

Content-disposition is an extension to the MIME protocol, MIME protocol indicates MIME user agent how to display the attached file.

The default value is inline, means open in a browser window.

When the server sends the file to the client's browser, if the browser supports the file type, generally use the default browser to open, such as txt, jpg, etc., will be displayed directly in the browser.

If you need to prompt the user to save, use Content-Disposition conduct some processing, the key is to be sure to add attachment.

For example: Content-Disposition: attachment; filename = xxx, the browser will activate the download dialog box, attachment representation annex, followed filname followed by the file name is displayed in the download box.

flow

Download is the response to the client bytes of data! Will become a file byte array, using response.getOutputStream ()

To respond to the browser.

The following code, the code has been implemented HTTP functionality, users can pause the download process, and continue to download, resulting in pressure on the server is relatively small.

String fid             = request.getHeader("id");

String blockIndex = request.getHeader("blockIndex");//基于1

String blockOffset = request.getHeader ( "blockOffset"); // block offset, relative to the entire file

String blockSize = request.getHeader ( "blockSize"); // block size (the size of the current to be downloaded)

String pathSvr = request.getHeader ( "pathSvr"); // file in the server's location

pathSvr            = PathTool.url_decode(pathSvr);

 

if (  StringUtils.isBlank(fid)

     ||StringUtils.isBlank(blockIndex)

     ||StringUtils.isEmpty(blockOffset)

     ||StringUtils.isBlank(blockSize)

     ||StringUtils.isBlank(pathSvr))

{

     response.setStatus(500);

     response.setHeader ( "err", "parameter is null");

     return;

}

File f = new File(pathSvr);

//file does not exist

if(!f.exists())

{

     response.setStatus(500);

     OutputStream os = response.getOutputStream();

     System.out.println (String.format ( "% s file does not exist", pathSvr));

     os.close();

     return;

}

long fileLen = f.length();

 

response.setContentType("application/x-download");

response.setHeader("Pragma","No-cache"); 

response.setHeader("Cache-Control","no-cache");

response.addHeader("Content-Length",blockSize); 

response.setDateHeader("Expires", 0);

 

OutputStream os = response.getOutputStream();

try

{

     RandomAccessFile raf = new RandomAccessFile(pathSvr,"r");

    

     int readToLen = Integer.parseInt(blockSize);

     int readLen = 0;

     raf.seek (Long.parseLong (blockOffset)); // fix index

     byte[] data = new byte[1048576];

    

     while( readToLen > 0 )

     {

         readLen = raf.read(data,0,Math.min(1048576,readToLen) );

         readToLen -= readLen;

         os.write(data, 0, readLen);

        

     }

     os.flush();

     os.close();  

     raf.close();

     os = null;

     response.flushBuffer();

    

     out.clear();

     out = pageContext.pushBody();

}

catch(Exception e)

{

     response.setStatus(500);

     os.close();

     out.close();

     e.printStackTrace ();

}

finally

{   

     if(os != null)

     {

         os.close();       

         os = null;

     }

     out.clear();

     out = pageContext.pushBody();

}%>

 

Load the file list, displayed in the download list

Most of the back-end code logic is the same, currently supports MySQL, Oracle, SQL. Before using the need to configure the database, you can refer me to write this article: 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 the discussion group "374 992 201" together

Guess you like

Origin www.cnblogs.com/songsu/p/12626011.html