1. Course Overview
In the development of web application system, file upload function is a very common function. Today, let’s mainly talk about the relevant technical implementation of file upload function in JavaWeb. With the rapid development of Internet technology, users’ experience requirements for websites are getting higher and higher. There are also many innovative points in the technology of file upload function, such as asynchronous uploading, drag-and-drop uploading, paste uploading, upload progress monitoring, file thumbnails, large file breakpoint continuous transmission, large file instant transmission, etc.
Basics required for this course:
Understand the basic Http protocol content
Basic IO stream operation technology
Basics of Servlet
Basic knowledge of javascript/jQuery technology
2. Basics of file upload
For file upload, the browser submits the file to the server side in the form of a stream during the upload process, and all streaming data will be carried to the server side with the Http request. Therefore, the format of the requested content when uploading the file must be basically understood.
File upload page:
<form action="/itheimaUpload/UploadServlet" method="post" enctype="multipart/form-data">Please select the uploaded file: <input type="file" name="attach"/><br/><input type="submit" value="submit"/></form>
Http request content:
3. Java background uses Servlet to receive files
It is troublesome if you use Servlet to obtain the input stream of uploaded files and then parse the request parameters in it. Therefore, generally speaking, the background chooses to use the common-fileupload file upload component, the open source tool of Apache.
//Java background code: Commons-fileUpload component uploads file public class UploadServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//1. Configure cache DiskFileItemFactory factory = new DiskFileItemFactory(1*1024*1024,new File("c:/tempFiles/"));//2. Create ServleFileUpload object ServletFileUpload sfu = new ServletFileUpload(factory);//Solve the Chinese problem of file name sfu.setHeaderEncoding("utf-8");//3. Resolve try {List<FileItem> list = sfu.parseRequest(request);//Resolve all content if(list!=null){for(FileItem item:list){//Determine whether it is a normal form parameter if(item.isFormField()){//Ordinary form parameters//Get the name attribute name of the form String fieldName = item.getFieldName();//Get the form parameter value String value = item.getString("utf-8"); }else{//File if(item.getName()!=null && !item.getName().equals("")) {//Save to server hard disk FileUtils.copyInputStreamToFile(item.getInputStream(), new File("c:/targetFiles/"+item.getName()));item.delete();}}}}} catch (FileUploadException e) {e.printStackTrace();}} public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}4. Use WebUploader to upload components
At the front end of the file upload page, we can choose to use some more useful upload components, such as Baidu's open source component WebUploader. This component can basically meet some daily functions of file upload, such as asynchronous uploading, drag-and-drop uploading, pasting uploading, upload progress monitoring, file thumbnails, and even large file breakpoints to continue transmission, and large file transmission in seconds.
Download the WebUpload component
http://fex.baidu.com/webuploader/ Download the WebUpload package at the WebUpload official website
WebUpload directory structure:
Basic file upload demo (including upload progress)
front end
1.1 Import the required css, js on the page
<link rel="stylesheet" type="text/css"href="${pageContext.request.contextPath}/css/webuploader.css"><script type="text/javascript"src="${pageContext.request.contextPath }/js/jquery-1.10.2.min.js"></script><script type="text/javascript"src="${pageContext.request.contextPath }/js/webuploader.js"></script>1.2 Write the upload page tag
<!-- Upload div --><div id="uploader"><!-- Display file list information--><ul id="fileList"></ul><!-- Select file area--><div id="filePicker">Click to select file</div></div>
1.3 Writing webupload code
<script type="text/javascript">//1. Initialize WebUpload and configure global parameters var uploader = WebUploader.create({//Flashk control address swf: "${pageContext.request.contextPath}/js/Uploader.swf",//Backend submission address server: "${pageContext.request.contextPath}/UploadServlet",//Select the file control's tag pick: "#filePicker",//Auto upload file auto:true,});//2. After selecting the file, the file information queue display // Register the fileQueued event: triggered when the file is added to the queue // file: Represents the currently selected file uploader.on("fileQueued",function(file){//Add file information div$("#fileList").append("<div id='"+file.id+"' class='fileInfo'><span>"+file.name+"</span><div class='state'>Waiting for upload...</div><span class='text'></span></div>");});//3. Register upload progress listening//file: Uploading file//percentage: The proportion of the current progress. The maximum is 1. For example: 0.2uploader.on("uploadProgress",function(file,percentage){var id = $("#"+file.id);//Update status information id.find("div.state").text("upload...");//Update upload percentage id.find("span.text").text(Math.round(percentage*100)+"%");});//4. Register and upload listening//file: uploaded file//response: data returned by the background, return uploader.on("uploadSuccess", function(file, response){//Update status information $("#"+file.id).find("div.state").text("uploaded");});2) Backend Servlet Code
DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload sfu = new ServletFileUpload(factory);sfu.setHeaderEncoding("utf-8");try {List<FileItem> items = sfu.parseRequest(request);for(FileItem item:items){if(item.isFormField()){//Normal information}else{//File information//Judge that only files need to be saved and processed System.out.println("Received file name:"+item.getName());//Copy the file to the hard disk in the background FileUtils.copyInputStreamToFile(item.getInputStream(), new File(serverPath+"/"+item.getName()));System.out.println("File saves successfully");}}} catch (FileUploadException e) {e.printStackTrace();}Generate image thumbnails
Key point: Call uploader.makeThumb() method to generate thumbnails
uploader.on("fileQueued",function(file){//Append file information div$("#fileList").append("<div id='"+file.id+"' class='fileInfo'><img/><span>"+file.name+"</span><div class='state'>Waiting for upload...</div><span class='text'></span></div>");//Make image thumbnails: Call makeThumb() method //error: Failed to create thumbnails //src: Path of thumbnails uploader.makeThumb(file,function(error,src){var id = $("#"+file.id);//If it fails, "cannot preview" is displayed if(error){id.find("img").replaceWith("cannot preview");} //If it succeeds, the thumbnail will be displayed to the specified position id.find("img").attr("src",src); });});Drag, paste and upload
1) Add a div to the drag area on the page
<!-- Upload div --><div id="uploader"><!-- File drag area--><div id="dndArea"><p>Drag the file directly here to automatically upload</p></div><!-- Display file list information--><ul id="fileList"></ul><!-- Select file area--><div id="filePicker">Click to select file</div></div>
2) Add drag and drop parameters to the global configuration parameters of the webuploader
//1. Initialize WebUpload and configure global parameters var uploader = WebUploader.create({//Flashk control address swf: "${pageContext.request.contextPath}/js/Uploader.swf",//Backend submission address server:"${pageContext.request.contextPath}/UploadServlet",//Select the file control's tag pick:"#filePicker",//Auto upload file auto:true,//Enable drag and drop function, specify the drag area dnd:"#dndArea",//Disable drag and drop function in other places of the page to prevent the page from directly opening the file disableGlobalDnd:true//Enable paste:"#uploader"});Upload large files in chunks
1) Add block upload parameters to the global parameters of the webuploader
//1. Initialize WebUpload and configure global parameters var uploader = WebUploader.create({//Flashk control address swf: "${pageContext.request.contextPath}/js/Uploader.swf",//Backend submission address server:"${pageContext.request.contextPath}/UploadServlet",//Select the file control's tag pick:"#filePicker",//Auto upload file auto:true,//Enable drag and drop function, specify the drag area dnd:"#dndArea",//Disable page Drag and drop function in other places to prevent the page from opening the file directly disableGlobalDnd:true,//Enable paste function paste:"#uploader",//Set in chunked:true,//Where to upload chunked:true,//File size per block (default 5M) chunkSize:5*1024*1024,//Open several concurrent threads (default 3) threads:3,//When uploading the current file, prepareNextFile:true});2) Monitor three time points for uploading files
After adding the above three configurations, you will find that when the file exceeds 5M, the webuploader will automatically send the file to the background.
Each block request contains information:
You can listen to three important time points in file uploads in chunks.
before-send-file: Call before-send before-send: If there are blocks, call after-send-file before each block is sent: Called after all blocks are sent //5. Monitor the three time points of uploading of the file (note: this section of code must be placed before WebUploader.create)//Time point 1:: Before all blocks are uploaded (1. The unique mark of the file can be calculated; 2. It can determine whether it is transmitted in seconds) //Time point 2: If uploading in chunks, before uploading each chunk (1. Ask the background whether the chunk has been saved successfully, for breakpoint continuous transmission) //Step 3: After all chunks are uploaded successfully (1. Notify the background of chunk files to merge) WebUploader.Uploader.register({"before-send-file":"beforeSendFile","before-send":"beforeSend","after-send-file":"afterSendFile"},{//Step 1:: Call this function before uploading in all chunks beforeSendFi le:function(){//1. Calculate the unique mark of the file, used for breakpoint continuous transmission and second transmission //2. Request whether the background has saved the file. If it exists, skip the file to realize the second transmission function},//Step 2: If there is a block upload, then call this function beforeSend:function(){//1. Request whether the background has saved the current block. If it exists, skip the block file to realize the breakpoint continuous transmission function},//Step 3: Call this function after all blocks are uploaded successfully afterSendFile:function(){//1. If it is uploaded in blocks, all block files are merged through the background}});before-send-file logic:
//Use md5File() method to calculate the unique tag of the file //This function receives a deferredbeforeSendFile:function(file){//Create a deferredvar deferred = WebUploader.Deferred();//1. Calculate the unique tag of the file, used for breakpoint continuous transmission and second transmission (new WebUploader.Uploader()).md5File(file,0,5*1024*1024).progress(function(percentage){$("#"+file.id).find("div.state").text("File information is being retrieved...");}).then(function(val){uniqueFileTag = val;$("#"+file.id).find("div.state").text("Successfully obtained file information");//Only when the file information is successfully obtained, the next operation will be performed deferred.resolve();});//alert(uniqueFileTag);//2. Request whether the background has saved the file. If it exists, the file will be skipped to realize the second pass function //Return deferred.promise();}before-send logic:
//Send a unique tag of the current file to the background, which is used to create a directory that saves the chunked file beforeSend:function(){//Carry the unique tag of the current file to the background, which is used to create a directory that saves the chunked file this.owner.options.formData.fileMd5 = fileMd5;}3) The background needs to save all chunked files
//Create a directory for each file and save all chunked files of this file //Judge whether it has been uploaded in chunks if(chunks!=null){System.out.println("chunk processing...");//Create a temporary directory to save all chunked files File chunksDir = new File(serverPath+"/"+fileMd5); if(!chunksDir.exists()){chunksDir.mkdir();}if(chunk!=null){//Save chunkFile chunkFile = new File(chunksDir.getPath()+"/"+chunk);FileUtils.copyInputStreamToFile(item.getInputStream(), chunkFile);}4) The front desk notifies the backend to merge all chunked files
//The front desk notifies the background to merge files after-send-file logic: afterSendFile:function(file){//1. If uploaded in chunks, merge all chunk files through the background //Request the background to merge files $.ajax({type:"POST",url:"${pageContext.request.contextPath}/UploadCheckServlet?action=mergeChunks",data:{//File Unique tag fileMd5:fileMd5,//File name fileName:file.name},dataType:"json",success:function(response){alert(response.msg);}});}//Background merge all chunked files if("mergeChunks".equals(action)){System.out.println("Start merge files...");//Merge file String fileMd5 = request.getParameter("fileMd5");String fileName = request.getParameter("fileName");//Read all files in the directory File f = new File(serverPath+"/"+fileMd5);File[] fileArray = f.listFiles(new FileFilter(){//Exclude directory, as long as the file public boolean accept(File pathname) {if(pathname.isDirectory()){return false;}return true;}});//Convert to a collection to facilitate sorting List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));//Sort from small to large Collections.sort(fileList, new Comparator<File>() {public int compare(File o1, File o2) {if(Integer.parseInt(o1.getName())) < Integer.parseInt(o2.getName())){return -1;}return 1;}});File outputFile = new File(serverPath+"/"+fileName);//Create the file outputFile.createNewFile();//Output stream FileChannel outChannel = new FileOutputStream(outputFile).getChannel();//Merge FileChannel inChannel; for(File file: fileList){inChannel = new FileInputStream(file).getChannel();inChannel.transferTo(0, inChannel.size(), outChannel);inChannel.close();//Delete shard file.delete();}//Clear folder File tempFile = new File(serverPath+"/"+fileMd5); if(tempFile.isDirectory() && tempFile.exists()){tempFile.delete();}//Close the stream outChannel.close();response.setContentType("text/html;charset=utf-8");response.getWriter().write("{/"msg/":/"merge successfully/"}");}Large file breakpoints continue
Based on the implementation of block upload, it is very simple to implement breakpoint continuous transmission! ! !
front end:
//Time point 2: If there is block upload, this function is called before each block upload //block: represents the current block object beforeSend:function(block){//1. Request whether the background has saved the current block. If it exists, skip the block file to realize the breakpoint continuous transmission function var deferred = WebUploader.Deferred();//Request whether the background saves the file information. If it has been saved, it will be skipped. If it has not, the chunk content will be sent $.ajax({type:"POST",url:"${pageContext.request.contextPath}/UploadCheckServlet?action=checkChunk",data:{//The file unique mark fileMd5:fileMd5,//The current chunk subscript chunk:block.chunk,//The current chunk size chunkSize:b lock.end-block.start},dataType:"json",success:function(response){if(response.ifExist){//The block exists, skip the block deferred.reject();}else{//The block does not exist or is incomplete, and resend the block content deferred.resolve();}}});//Carry the unique tag of the current file to the background, and let the background create the directory that saves the file blocks this.owner.options.formData.fileMd5 = fileMd5;return deferred.promise(); },Backstage:
//Check whether the chunk exists or saves private void checkChunk(HttpServletRequest request,HttpServletResponse response) throws IOException,FileNotFoundException {System.out.println("checkChunk...");String fileMd5 = request.getParameter("fileMd5");String chunk = request.getParameter("chunk");String chunkSize = request.getParameter("chunkSize");File checkFile = new File(serverPath+"/"+fileMd5+"/"+chunk);response.setContentType("text/html;charset=utf-8");//Check whether the file exists and the size is consistent if(checkFile.exists() && checkFile.length()==Integer.parseInt(chunkSize)){response.getWriter().write("{/"ifExist/":1}");}else{response.getWriter().write("{/"ifExist/":0}");}}File transfer in seconds
Before all block requests, the second transfer function can be implemented! ! !
front end:
beforeSendFile:function(file){//Create a defferedvar deferred = WebUploader.Deferred();//1. Calculate the unique mark of the file, used for breakpoint continuous transmission and second transmission (new WebUploader.Uploader()).md5File(file,0,5*1024*1024).progress(function(percentage){$("#"+file.id).find("div.state").text("get file information...");}).then(function(val){fileMd5 = val;$("#"+file.id).find("div.state").text("Successfully obtained file information");//2. Request whether the background has saved the file. If it exists, skip the file to realize the second pass function $.ajax({type:"POST",url:"${pageContext.request.contextPath}/UploadCheckServlet?action=fileCheck",data:{//The file's unique tag fileMd5:fileMd5},dataType:"json",success:function(response){if(response.ifExist){$("#"+file.id).find("div.state").text("Successfully transferred"); //If it exists, skip the file and pass it successfully in seconds to deferred.reject();}else{//Continue to upload deferred.resolve();}}});});//Return deferredreturn deferred.promise();},Backstage:
//Check whether the md5 data of the file is related to the database private void fileCheck(HttpServletRequest request,HttpServletResponse response) throws IOException,FileNotFoundException {String fileMd5 = request.getParameter("fileMd5");//Simulate the database Map<String,String> database = new HashMap<String,String>();database.put("576018603f4091782b68b78af85704a1", "01. Course Review.itcast");response.setContentType("text/html;charset=utf-8");if(database.containsKey(fileMd5)){response.getWriter().write("{/"ifExist/":1}");}else{response.getWriter().write("{/"ifExist/":0}");}}The above is an example explanation of JavaWeb file upload and download that the editor introduced to you (cool file upload technology). I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!