What is file upload?
File upload is to save user information.
Why do I need to upload a file?
When a user registers, the user may need to submit a photo. Then this photo should be saved.
Upload components (tools) Why do we need to use the upload tool?
Why do we need to upload components? When we want to get the client's data, we usually get it through the getParameter() method.
The uploaded file data is divided by MIME protocol, and the form is encapsulated in binary. In other words: getParameter() cannot get the data of the uploaded file.
Let's first look at how http file uploads bring data with you
jsp page, form must specify enctype: multipart/form-data
<form action="${pageContext.request.contextPath }/servlet/UploadServlet1" enctype="multipart/form-data" method="post"> Upload user: <input type="text" name="username"><br/> Upload file 1: <input type="file" name="file1"><br/> Upload file 2: <input type="file" name="file2"><br/> <input type="submit" value="submit"> </form>http package grabbing
Try to get data using getParameter() on Servlet
String ss = request.getParameter("username");System.out.println(ss);You cannot get the data by directly using getParameter.
So what should we do? ? ? ? The request object provides the ServletInputStream stream to read the data to us
We try to read the file
ServletInputStream inputStream = request.getInputStream(); byte[] bytes = new byte[1024]; int len = 0; while ((len = inputStream.read(bytes)) > 0) { System.out.println(new String(bytes, 0, len)); }Add an additional input control to the jsp page
<input type="text" name="password">
The text file I uploaded is 111111, and the reading effect is as follows:
Now we can read the data of uploading files, but now the question is: How to separate the uploaded data of the file from the data sent to the server? ? ? We have seen above in the picture, they are mixed together.
It is difficult to separate according to our usual practice, so we need to upload components
There are two types of FileUploads upload components [more operation] SamrtUpload [more operation] FileUpload
To use the FileUpload component, you need to import two jar packages
commons-io Commons-fileupload Development steps Create a parser factory object [DiskFileItemFactory] Create a parser through the parser factory [ServletFileUpload] Call the parser method to parse the request object, get all uploaded contents [list] traversing the list, determine whether each object is an uploaded file. If it is a normal form field, get the field name and field value. If it is an uploaded file, call the InputSteam method to get the input stream, read the uploaded data quickly.
try{ //1. Get the parser factory DiskFileItemFactory factory = new DiskFileItemFactory(); //2. Get the parser ServletFileUpload upload = new ServletFileUpload(factory); //3. Determine the type of uploading form if(!upload.isMultipartContent(request)){ // Upload the form is a normal form, then obtain the data in the traditional way to return; } // To upload the form, call the parser to parse the uploaded data List<FileItem> list = upload.parseRequest(request); //FileItem //Transfuse the list and get the fileItem object used to encapsulate the first upload input item data fileItem object for(FileItem item : list){ if(item.isFormField()){ //What you get is the normal input item String name = item.getFieldName(); //Get the name of the input item String value = item.getString(); System.out.println(name + "=" + value); }else{ //Get the upload input item String filename = item.getName(); //Get the upload filename C:/Documents and Settings/ThinkPad/Desktop/1.txt filename = filename.substring(filename.lastIndexOf("//")+1); InputStream in = item.getInputStream(); //Get upload data int len = 0; byte buffer[]= new byte[1024]; String savepath = this.getServletContext().getRealPath("/upload"); FileOutputStream out = new FileOutputStream(savepath + "//" + filename); //Write file to the upload directory while((len=in.read(buffer))>0){ out.write(buffer, 0, len); } in.close(); out.close(); } } } catch (Exception e) { e.printStackTrace(); }Testing that both ordinary fields and uploaded files can be read and obtained!
SmartUpload
To use the SmartUpload component, you need to import the smartupload.jar development package
Quick Start
//Instantiated component SmartUpload smartUpload = new SmartUpload(); //Initialize the upload operation smartUpload.initialize(this.getServletConfig(), request, response); try { //Upload preparation smartUpload.upload(); //For ordinary data, it is so simple that the request object cannot obtain the submitted parameters. Also, you need to rely on smartUpload String password = smartUpload.getRequest().getParameter("password"); System.out.println(password); //Upload to uploadFile folder smartUpload.save("uploadFile"); } catch (SmartUploadException e) { e.printStackTrace(); }test
Similarly, we can upload files to the uploadFile folder. The amount of code is indeed reduced a lot!
You can also get parameters of normal fields
I changed the file name to Chinese garbled code and Chinese garbled code for uploading data, and it was garbled code:
The Chinese data submitted by the form is also garbled.
As mentioned above, the form of uploading the file data is encapsulated in binary, so using request to encode the data will not work for the data submitted by the form!
FileUpload solves garbled code
Using FileUpload to solve garbled problems is very simple
Solve the garbled Chinese file name. After obtaining the parser, just set the encoding of the parser to UTF-8!
//Set the encoding of upload fileUpload.setHeaderEncoding("UTF-8");Solve the garbled form data. When obtaining form values, use UTF-8 encoding to obtain them.
String value = fileItem.getString("UTF-8");Effect:
SmartUpload solves garbled code
This component is a bit troublesome to solve the problem of garbled code. I found various solutions online but couldn't find a simple one...
Therefore, if the data does not involve Chinese, use the SmartUpload component, and if it involves Chinese data, use the FileUpload component!
Upload multiple files, dynamically add upload controls
Suppose I have multiple files to upload now, and the number of files to upload is uncertain. So what should we do? ? ?
It is impossible for us to list many controls for uploading files on the page, which is not beautiful. If the user can't use so many controls, it's a waste.
Therefore, we want to dynamically add controls for uploading files. If the user also wants to upload files, he only needs to dynamically generate controls!
analyze
To generate controls dynamically on the page, it is nothing more than using JavaScript code.
So what do we do? ?
Let's do this: When the user wants to upload a file, click the button, and the button binds the event to generate the control for file upload.
In order to do more perfectly, whenever a file upload control is generated, a delete button is also provided to delete the control!
We should use div to load the controls and delete buttons we want to generate. When the user clicks to delete, they should hide the delete button and file upload controls together. So, it's best to use nested divs!
Code page code:
<table> <tr> <td>Upload user: </td> <td><input type="text" name="username"></td> </tr> <tr> <td>Add upload file</td> <td><input type="button" value="Add upload file"> </td> </tr> <tr> <td> <div> </div> </td> </td> </tr></table>
javaScript code
<script type="text/javascript"> function addUploadFile() { // Generate file upload control var input = document.createElement("input"); input.type = 'file'; input.name = 'fileName'; // Generate delete button var del = document.createElement("input"); del.type = 'button'; del.value = 'delete'; // Generate internal div var innerDiv = document.createElement("div"); // Bind two controls to innerDiv.appendChild(input); innerDiv.appendChild(del); //Get the external div control and bind the internal div to the external div var outterDiv = document.getElementById("file"); outterDiv.appendChild(innerDiv); //Bind event del.onclick = function delete() { //Calling the remove method of the external div to kill the internal div this.parentNode.parentNode.removeChild(this.parentNode); } } </script>File upload details If the size of the uploaded file is greater than the size of the file we set, then the file will use a temporary file to save the uploaded data when uploading. After uploading, we should delete the temporary file. The location where the upload file cannot be managed by the WEB server, otherwise it may cause security problems [others may modify the upload file through means] If the upload file name is the same, the original upload file will be overwritten. We want to generate a unique file name. If the number of users is large, there are many files uploaded. Then we should not save all upload files in one directory, which is likely to cause the disk to crash. So we have to disperse the uploaded files to different directories. analyze
The problem of deleting temporary files is very simple. You only need to call the delete() method of FileItem after all operations are completed.
To prevent the uploaded file from being managed by the WEB server, we can just place the uploaded file location in the WEB-INF/ directory!
For the same file name, we can use UUID+ file name uploaded by the user as our save uploaded file name. Such a file name is unique.
To break up the uploaded files, we need to use the HashCode algorithm to break up.
The lower four bits generate first-level directory 5-8 bits generate second-level directory code
Let's write a relatively complete upload file code
Use hashCode algorithm to break up saved directories
private String makeDirPath(String fileName, String path) { // Calculate the primary and secondary directories through the file name int hashCode = fileName.hashCode(); int dir1 = hashCode & 0xf; int dir2 = (hashCode & 0xf0) >> 4; String dir = path + "//" + dir1 + "//" + dir2; //If the directory does not exist, create the directory File file = new File(dir); if (!file.exists()) { file.mkdirs(); } //Return the full path return dir; }Generate unique file names
private String makeFileName(String fileName) { //Use underscore to separate the UUID and the file name, and the file name may be parsed later. return UUID.randomUUID().toString() + "_"+ fileName; }Uploaded code
//Create factory DiskFileItemFactory factory = new DiskFileItemFactory(); //Create a parser through the factory ServletFileUpload fileUpload = new ServletFileUpload(factory); //Set the code of upload fileUpload.setHeaderEncoding("UTF-8"); //Judge the type of upload form if(!fileUpload.isMultipartContent(request)){ //Upload the form as a normal form, then obtain the data in the traditional way to return; } try { //Parse the request object to get List [load all the uploaded content] List<FileItem> list = fileUpload.parseRequest(request); //Travel through List to determine whether the loaded content is a normal field or an upload file for (FileItem fileItem : list) { //If it is a normal input item if (fileItem.isFormField()) { //Get the name and value of the input item String name = fileItem.getFieldName(); String value = fileItem.getString("UTF-8"); System.out.println(name + " = " + value); } else { //If it is an upload file//Get the upload name [including path name] String fileName = fileItem.getName(); //Intercept the file name fileName = fileName.substring(fileName.lastIndexOf("//") + 1); //Generate a unique file name fileName = makeFileName(fileName); InputStream inputStream = fileItem.getInputStream(); //Get the project path and write the uploaded file to the project String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile"); //Get the scattered directory path String realPath = makeDirPath(fileName, path); FileOutputStream outputStream = new FileOutputStream(realPath + "//" + fileName); byte[] bytes = new byte[1024]; int len = 0; while ((len = inputStream.read(bytes)) > 0) { outputStream.write(bytes, 0, len); } inputStream.close(); outputStream.close(); //Delete the data of the temporary file fileItem.delete(); } } } catch (FileUploadException e) { e.printStackTrace(); }Effect: The directory was successfully broken up, and the file name was unique.
List the files in the uploaded directory and provide downloads
When explaining the respose object, the file download has been explained. This time we will write a small case to consolidate the file download.
There are 3 files in the upload directory
analyze
First, list all the files in the directory. Since we need to download the file according to the file name later, we use a Map collection to save all files
The downloading part is also very simple. Find the corresponding file according to the file name and upload file location, read and write it, and then modify the message header to achieve downloading.
Get the path to load and upload files, find out all files by recursively (judging whether it is a file or is a recursive exit), load it into the Map collection and pass the Map collection to the front desk to display when the user clicks to download, and then obtain the absolute path according to the original name. If the resource exists, the user is allowed to download the code and put all the files stored in the WEB-INF/ directory in the Map collection.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the directory where the uploaded file is String filePath = this.getServletContext().getRealPath("/WEB-INF/uploadFile"); Map map = new HashMap(); //Use recursion to get all files and add them to the Map collection getAllFiles(new File(filePath), map); request.setAttribute("map", map); request.getRequestDispatcher("/listFile.jsp").forward(request, response); } private void getAllFiles(File filePath, Map map) { //If it is not a file, then it is a folder if (!filePath.isFile()) { //List all files in the folder (maybe a file, maybe a folder) File[] files = filePath.listFiles(); for (File file: files) { //Judge the obtained file (or folder) and getAllFiles(file, map); } } else { //Enter the else statement, it must be a file //Get the file name String fileName = filePath.getName().substring(filePath.getName().lastIndexOf("_") + 1); //We save the full name of the file as the key and the file name as the value in the map collection map.put(filePath.getName(), fileName); } }Show downloadable files in JSP page
<c:forEach items="${map}" var="me"> <c:url var="url" value="/DownFileServlet"> <c:param name="fileName" value="${me.key}"></c:param> </c:url> ${me.value}<a href="${url}" rel="external nofollow" >Download! </a><br></c:forEach>Implement the downloaded servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the full name of the file String fileName = request.getParameter("fileName"); //If it is Chinese data, transcoding is required. fileName = new String(fileName.getBytes("ISO8859-1"), "utf-8"); //Get the location where the file is saved String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile"); //The file is saved through the file name by hashCode, and the file is obtained through the file name String fileRealPath = makeFilePath(fileName, path); System.out.println(fileRealPath); //Judge whether the file exists File file = new File(fileRealPath); if (!file.exists()) { request.setAttribute("message", "The resource you want to download does not exist!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return ; } //exist//Read the file and write the data to the browser FileInputStream inputStream = new FileInputStream(fileRealPath); byte[] bytes = new byte[1024]; int len = 0; while ((len = inputStream.read(bytes)) > 0) { response.getOutputStream().write(bytes, 0, len); } inputStream.close(); //Set the message header to tell the browser that this is the downloaded file String name = fileName.substring(fileName.lastIndexOf("_") + 1); response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(name, "UTF-8")); } private String makeFilePath(String fileName, String path) { int hashCode = fileName.hashCode(); int dir1 = hashCode & 0xf; int dir2 = (hashCode & 0xf0) >> 4; String dir = path + "//" + dir1 + "//" + dir2 +"//"+ fileName; return dir; }Effect
If there is any error in the article, please correct me and everyone will communicate with each other. Thank you for your support to Wulin.com.