22. Introduction to servlet - file download case
Case - complete file download
1. Demand analysis
- Create the page of file download list, click some links in the list to download the file
img/
2. File download analysis
2.1 what is file download
Output the existing files on the server to the client browser
To put it bluntly, a copy of the server-side file is copied to the client, and the copy of the file -- > stream (input stream and output stream) is copied
2.2 file download method
- First: hyperlink (not recommended) Link method: directly write the path of the file on the server to the href attribute. If the browser does not support this format file, you will be prompted to download it. If If the browser supports files in this format (eg: png, jpg...), open them directly and don't download them anymore
- Second: manual coding (recommended) Manually write code to download. Whether the browser recognizes the file in this format or not, it will be downloaded
3. Train of thought analysis
3.1 hyperlink mode
- Resources (files) ready to download
- Write a download page
- Define hyperlinks on this page and specify href
3.2 coding method
3.2.1 requirements for manual coding mode
Set two headers and a stream
Set two headers:
Content disposal: the server tells the browser to download
Content type: tells the browser the file type. (MIME type)
Set a stream:
Get the input stream of the file to download
3.2.2 ideas
image-20191209150057781
4. Code implementation
4.1 resources (files) to be downloaded
image-20210109125818515
4.2 write a download.html page for download
image-20210109130037678
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="/download?fileName=1.jpeg">Download 1.jpeg</a><br> <a href="/download?fileName=3.png">Download 3.png</a><br> <a href="/download?fileName=demo.zip">download demo.zip</a><br> <a href="/download?fileName=venom.jpeg">Download venom.jpeg</a><br> </body> </html>
Start tomcat and visit the following page:
image-20210109130130807
Now that the html page has been written, the following is the implementation of the Servlet program.
4.3 write a Servlet program to handle the download service
4.3.1 write the receiving file name first
image-20210109135318506
@WebServlet("/download") public class DownloadDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Solve the Chinese garbled code of request parameters request.setCharacterEncoding("UTF-8"); //Solve Chinese garbled code in response response.setContentType("text/html;charset=utf-8"); //1. Receive parameters and obtain the file name to be downloaded String fileName = request.getParameter("fileName"); System.out.println("File name to download: " + fileName); } }
Access download.html in the browser to view the obtained file name:
image-20210109135547460
4.3.2 splice the file download path, read the file byte stream, and output it to the browser
image-20210109140134502
@WebServlet("/download") public class DownloadDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Solve the Chinese garbled code of request parameters request.setCharacterEncoding("UTF-8"); //Solve Chinese garbled code in response response.setContentType("text/html;charset=utf-8"); //1. Receive parameters and obtain the file name to be downloaded String fileName = request.getParameter("fileName"); System.out.println("File name to download: " + fileName); //2. Splice the file download path, read the file byte stream output and display it on the browser InputStream is = getServletContext().getResourceAsStream("file/" + fileName); // Get file input byte stream ServletOutputStream os = response.getOutputStream(); // Get browser output stream IOUtils.copy(is, os); //3. Close resources os.close(); is.close(); } }
The browser accesses a file as follows:
image-20210109140300491
You can see that bytecode data is displayed. We can set the response header to inform the browser of the file type, and then the browser will display it accordingly.
4.3.3 set the file type displayed by the browser
image-20210109140518071
//3. Set the file type displayed by the browser String mimeType = getServletContext().getMimeType(fileName); response.setHeader("Content-Type",mimeType);
Browser access is as follows:
image-20210109140540217
image-20210109140638050
When you click the. zip file, you will be prompted to download it.
image-20210109140810631
4.3.4 download files through the browser and set the downloaded file name
When we open the picture above, it is displayed directly in the browser. What should we do if we want to download it directly?
In addition, when downloading the demo.zip file, it is found that the file name is changed to download.zip after downloading, so how to set the downloaded file name?
We can handle this by setting the response header:
response.setHeader("Content-Disposition","attachment;filename="+fileName);
The implementation code is as follows:
image-20210109141354809
The browser test is as follows:
image-20210109141422338
image-20210109141452948
We can see that if the downloaded file is in Chinese, the file name cannot be displayed normally.
5. Solve the problem of garbled file names in downloading Chinese
In the above, when we download files with Chinese names, there will be garbled code, so how to solve it?
In fact, it's still the problem of coding format. Just set the coding format. Let's take a look at the settings.
Chinese files are encoded differently in different browsers: Firefox is Base64 encoded, and other browsers (Google) are utf-8 encoded URL s
image-20210109142711952
@WebServlet("/download") public class DownloadDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Solve the Chinese garbled code of request parameters request.setCharacterEncoding("UTF-8"); //Solve Chinese garbled code in response response.setContentType("text/html;charset=utf-8"); //1. Receive parameters and obtain the file name to be downloaded String fileName = request.getParameter("fileName"); System.out.println("File name to download: " + fileName); //2. Splice the file download path, read the file byte stream output and display it on the browser InputStream is = getServletContext().getResourceAsStream("file/" + fileName); // Get file input byte stream ServletOutputStream os = response.getOutputStream(); // Get browser output stream //3. Set the file type displayed by the browser String mimeType = getServletContext().getMimeType(fileName); response.setHeader("Content-Type",mimeType); // Chinese files are encoded differently in different browsers: Firefox is Base64 encoded, and other browsers (Google) are utf-8 encoded URL s // Gets the type of browser //Automatically set different encoding methods String ua = request.getHeader("User-Agent"); // Determine whether it is Firefox if (ua.contains("Firefox")) { // After BASE64 encoding using the following format String attachmentFile = "attachment; fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode(fileName.getBytes("utf-8")) + "?="; // Set to response header response.setHeader("Content-Disposition", attachmentFile); } else { // UTF-8 encoding the Chinese name. String attachmentFile = "attachment; fileName=" + URLEncoder.encode(fileName, "UTF-8"); // Then set the encoded string into the response header response.setHeader("Content-Disposition", attachmentFile); } //4. Output byte stream data to browser IOUtils.copy(is, os); //3. Close resources os.close(); is.close(); } }
The browser test is as follows:
image-20210109142801275