Getting started with Servlet - file download case

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

  1. Resources (files) ready to download
  2. Write a download page
  3. 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

Posted by cpd259 on Thu, 11 Nov 2021 22:57:28 -0800