Study Note 4: File upload and download

File upload and download

When surfing the Internet, we will encounter many cases of uploading and downloading, such as uploading and downloading pictures. Next, let's take a look at how the servlet implements uploading and downloading.

File upload

File upload involves the writing of the foreground page and the background server-side code, the foreground sends the file, and the background accepts and saves the file. This is a complete file upload.

Front page:

When uploading files, there will be an interface for uploading files. First, a form is required, and the request method is POST; secondly, the enctype of the form must be set to "multipart/form-data" , that is, enctype = "multipart/form- data" means to set the type of the form to the file upload form. By default, this form type is "application/x-www-from-urlencoded" and cannot be used for file upload. Only when multipart/form-data is used can the data file be completely transferred.

<form action="uploadServlet" method="post" enctype="multipart/form-data">
    姓名:<input type="text" name="uname">
    文件:<input type="file" name="myfile">
    <button>提交</button>
</form>

Background implementation:

Use the annotation @MultipartConfig to identify a servlet as supporting file upload. The Servlet encapsulates the multipart/form-data POST request into a Part object, and operates the uploaded file through the Part object .

package com.xxxx.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;

@WebServlet("/uploadServlet")
@MultipartConfig  //如果是文件上传,必须要加这个注解 让这个Servlet支持文件上传
public class UploadServlet extends HttpServlet {
    
    

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        System.out.println("文件上传...");

        //设置请求的编码格式
        request.setCharacterEncoding("utf-8");
        //获取普通表单项
        String uname = request.getParameter("uname");//参数为表单中表单元素的name属性值
        System.out.println("uname = " + uname);

        //获取part对象
        Part part = request.getPart("myfile");//参数为表单中file文件域的name属性值
        String fileName = part.getSubmittedFileName(); //获取提交过来的文件名
        System.out.println("filename = "+fileName);


        String filePath = request.getServletContext().getRealPath("/");//项目根目录
        System.out.println("filepath = "+filePath);
        //上传文件到指定目录(现在我们放在根目录下)
        part.write(filePath+"/"+fileName);

    }
}

Before servlet3.0 version, you need to use the third-party jar package commons-fileupload to upload files. Servlet3.0 and above have built-in api for uploading files. No third-party jar package
servlet3.0 and above. Save the uploaded files in Part In the example, the corresponding part object can be obtained according to the name of the uploaded form control through the request object. At the same time, it also supports multiple file uploads
. The troublesome part is obtaining the file name, because the saved file cannot be saved with the file name at the time of upload. Because we are afraid that many people will upload the same file name and be overwritten, it is generally necessary to set a random file name that cannot be repeated. We can use UUID as the file name. As for the suffix name, it needs to be obtained according to the file suffix when uploading, part The object itself does not store the name of the uploaded file. We need to get the file name from the request header information. When the browser sends the file upload request, the file name is stored in the Content-Disposition in the Request Head, but the Content-Disposition has a value. In addition to the file name information, there are some other information, so the file extension can only be obtained by string interception.

Content-Disposition:form-data; name=“file”; filename=“test.txt”

The file is stored in the upload folder under the root directory of the server's current project. Obtain the server's absolute value through req.getServletContext().getRealPath() and then write the uploaded file.

file download

File download is to download the resources on the server to the local client. There are two ways. The first is to download through the characteristics of the hyperlink itself, and the second is to download through code operations.
Most of the file downloads of the web project do not need to write code to achieve, only through the hyperlink can be achieved, that is, through the hyperlink, write the path of the file in the connection address, the browser will automatically open the file, if it is a normal text, Images and other browsers that can directly display content can be opened and displayed directly, but if it is a file that cannot be opened by the browser, such as rar, docx, exe, etc., then the browser will prompt you to download the modified file or use the current Open the file with the tool that comes with the system

Hyperlink download :

When we use the a tag in the page, we hope to be able to jump if we like, but when the hyperlink encounters a resource that the browser does not recognize, it will also be automatically downloaded;
when it encounters a resource that the browser can directly display, the browser will default Displayed, such as txt, png, jpg, etc. Of course, you can also specify the browser to download through the download attribute . But some browsers do not support it.

<!-- 当超链接遇到不识别的资源时,会自动下载-->
<a href="test.zip">超链接下载</a>

Specify the download attribute to download:

<!--当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性可进行强制下载-->
<a href="test.txt" download>超链接下载</a>

The download attribute does not need to write any information, and the default file name is automatically used. If the value of the download attribute is set, the set value is used as the file name. When the user clicks on the link, it will be downloaded directly.

It should be noted that if you want the browser to be able to access the resources in the project, you should configure the addition of external resources in Tomcat, as follows:
Insert picture description here

Download in the background :

Implementation steps:

  1. You need to use the response.setContentType method to set the value of the Content-Type header field to a MIME type that the browser cannot activate a program in some way to process, such as "application/octet-stream" or "application/x-msdownload".
  2. The value of the Content-Disposition header needs to be set to attachment through the response.setHeader method; filename=file name
  3. Read the downloaded file and call the response.getOutputStream method to write the content of the attachment to the client.
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    
    
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("文件下载...");
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        String fileName = request.getParameter("fileName");
        //判空 是否输入文件名
        if (fileName == null || "".equals(fileName.trim())){
    
    
            response.getWriter().write("请输入要下载的文件名!");
            response.getWriter().close();
            return;
        }
        //获取download文件夹的绝对路径(也就是存放项目资源的路径)
        String realPath = request.getServletContext().getRealPath("/download/");//获取download文件夹的绝对路径
        //通过路径获得这个file对象
        File file = new File(realPath+fileName);
        //判断这个文件是否存在并且是一个标准文件
        if (file.exists() && file.isFile()){
    
    
            //设置响应类型 浏览器无法使用某种方式激活某个程序来处理的 MIME 类型
            response.setContentType("application/octet-stream");
            //设置响应头
            response.setHeader("Content-Disposition","attachment;filename="+fileName);
            //得到这个文件的输入流
            InputStream in = new FileInputStream(file);
            //得到字节输出流
            ServletOutputStream out = response.getOutputStream();
            //定义byte数组
            byte[] bytes = new byte[1024];
            //定义长度
            int len = 0;
            //循环读取
            while((len = in.read(bytes)) != -1){
    
    
                out.write(bytes,0,len);
            }
            out.flush();
            out.close();
            in.close();

        }else{
    
    
            response.getWriter().write("文件不存在,请重试!");
            response.getWriter().close();
        }
    }
}

Knowledge link :

Content-disposition is an extension of the MIME protocol, which instructs the MIME user agent how to display attached files. When Internet Explorer receives the header, it activates the file download dialog box, and its file name box is automatically filled with the file name specified in the header. (Please note that this is by design; this function cannot be used to save documents to the user's computer without asking the user for the save location.)

When the server sends a file to the client browser, if it is a file type supported by the browser, it will generally be opened by the browser by default, such as txt, jpg, etc., which will be displayed directly in the browser. If you need to prompt the user to save, you must To use Content-Disposition for processing, the key is to add attachment:

Response.AppendHeader(“Content-Disposition”,“attachment;filename=FileName.txt”);

Note: In this way, the browser will prompt to save or open, even if you choose to open, it will use the associated program such as Notepad to open it instead of IE directly.

Guess you like

Origin blog.csdn.net/qq_40492885/article/details/115265405