Request&Response

来源:https://www.cnblogs.com/p1ng/archive/2020/02/22/12346949.html

這兩天複習了下Request以及Response部分的內容。 主要內容 1. HTTP協議:響應消息 2. Request對象 3. Response對象 4. ServletContext對象 HTTP: 概念:Hyper Text Transfer Protocol 超文本傳輸協議 傳輸協議:定 ...


這兩天複習了下Request以及Response部分的內容。

主要內容

  1. HTTP協議:響應消息
  2. Request對象
  3. Response對象
  4. ServletContext對象

HTTP:

* 概念:Hyper Text Transfer Protocol 超文本傳輸協議
    * 傳輸協議:定義了,客戶端和伺服器端通信時,發送數據的格式
    * 特點:
        1. 基於TCP/IP的高級協議
        2. 預設埠號:80
        3. 基於請求/響應模型的:一次請求對應一次響應
        4. 無狀態的:每次請求之間相互獨立,不能交互數據

    * 歷史版本:
        * 1.0:每一次請求響應都會建立新的連接
        * 1.1:復用連接

1. 請求消息:客戶端發送給伺服器端的數據
    * 數據格式:
        1. 請求行
            請求方式 請求url 請求協議/版本
            GET /login.html HTTP/1.1

            * 請求方式:
                * HTTP協議有7種請求方式,常用的有2種
                    * GET:
                        1. 請求參數在請求行中,在url後。
                        2. 請求的url長度有限制的
                        3. 不太安全
                    * POST:
                        1. 請求參數在請求體中
                        2. 請求的url長度沒有限制的
                        3. 相對安全
        2. 請求頭:客戶端瀏覽器告訴伺服器一些信息
            請求頭名稱: 請求頭值
            * 常見的請求頭:
                1. User-Agent:瀏覽器告訴伺服器,我訪問你使用的瀏覽器版本信息
                    * 可以在伺服器端獲取該頭的信息,解決瀏覽器的相容性問題

                2. Referer:http://localhost/login.html
                    * 告訴伺服器,我(當前請求)從哪裡來?
                        * 作用:
                            1. 防盜鏈
                            2. 統計工作
        3. 請求空行
            空行,就是用於分割POST請求的請求頭,和請求體的。
        4. 請求體(正文):
            * 封裝POST請求消息的請求參數的

    * 請求字元串格式:
        POST /login.html    HTTP/1.1
        Host: localhost
        User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
        Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
        Accept-Encoding: gzip, deflate
        Referer: http://localhost/login.html
        Connection: keep-alive
        Upgrade-Insecure-Requests: 1
        
        username=zhangsan   


2. 響應消息:伺服器端發送給客戶端的數據
    * 數據格式:
        1. 響應行
            1. 組成:協議/版本 響應狀態碼 狀態碼描述
            2. 響應狀態碼:伺服器告訴客戶端瀏覽器本次請求和響應的一個狀態。
                1. 狀態碼都是3位數字 
                2. 分類:
                    1. 1xx:伺服器接受客戶端消息,但沒有接受完成,等待一段時間後,發送1xx多狀態碼
                    2. 2xx:成功。代表:200
                    3. 3xx:重定向。代表:302(重定向),304(訪問緩存)
                    4. 4xx:客戶端錯誤。
                        * 代表:
                            * 404(請求路徑沒有對應的資源) 
                            * 405:請求方式沒有對應的doXxx方法
                    5. 5xx:伺服器端錯誤。代表:500(伺服器內部出現異常)
                        
                
        2. 響應頭:
            1. 格式:頭名稱: 值
            2. 常見的響應頭:
                1. Content-Type:伺服器告訴客戶端本次響應體數據格式以及編碼格式
                2. Content-disposition:伺服器告訴客戶端以什麼格式打開響應體數據
                    * 值:
                        * in-line:預設值,在當前頁面內打開
                        * attachment;filename=xxx:以附件形式打開響應體。文件下載
        3. 響應空行
        4. 響應體:傳輸的數據


    * 響應字元串格式
        HTTP/1.1 200 OK
        Content-Type: text/html;charset=UTF-8
        Content-Length: 101
        Date: Wed, 06 Jun 2018 07:08:42 GMT

        <html>
          <head>
            <title>$Title$</title>
          </head>
          <body>
          hello , response
          </body>
        </html>

Request:

1. request對象和response對象的原理
    1. request和response對象是由伺服器創建的。我們來使用它們
    2. request對象是來獲取請求消息,response對象是來設置響應消息

2. request對象繼承體繫結構: 
    ServletRequest      --  介面
        |   繼承
    HttpServletRequest  -- 介面
        |   實現
    org.apache.catalina.connector.RequestFacade 類(tomcat)

3. request功能:
    1. 獲取請求消息數據
        1. 獲取請求行數據
            * GET /day14/demo1?name=zhangsan HTTP/1.1
            * 方法:
                1. 獲取請求方式 :GET
                    * String getMethod()  
                2. (*)獲取虛擬目錄:/day14
                    * String getContextPath()
                3. 獲取Servlet路徑: /demo1
                    * String getServletPath()
                4. 獲取get方式請求參數:name=zhangsan
                    * String getQueryString()
                5. (*)獲取請求URI:/day14/demo1
                    * String getRequestURI() : /day14/demo1
                    * StringBuffer getRequestURL() : http://localhost/day14/demo1

                    * URL:統一資源定位符 : http://localhost/day14/demo1    中華人民共和國
                    * URI:統一資源標識符 : /day14/demo1                    共和國
    
                6. 獲取協議及版本:HTTP/1.1
                    * String getProtocol()

                7. 獲取客戶機的IP地址:
                    * String getRemoteAddr()
                
        2. 獲取請求頭數據
            * 方法:
                * (*)String getHeader(String name):通過請求頭的名稱獲取請求頭的值
                * Enumeration<String> getHeaderNames():獲取所有的請求頭名稱
            
        3. 獲取請求體數據:
            * 請求體:只有POST請求方式,才有請求體,在請求體中封裝了POST請求的請求參數
            * 步驟:
                1. 獲取流對象
                    *  BufferedReader getReader():獲取字元輸入流,只能操作字元數據
                    *  ServletInputStream getInputStream():獲取位元組輸入流,可以操作所有類型數據
                        * 在文件上傳知識點後講解

                2. 再從流對象中拿數據
            
            
    2. 其他功能:
        1. 獲取請求參數通用方式:不論get還是post請求方式都可以使用下列方法來獲取請求參數
            1. String getParameter(String name):根據參數名稱獲取參數值    username=zs&password=123
            2. String[] getParameterValues(String name):根據參數名稱獲取參數值的數組  hobby=xx&hobby=game
            3. Enumeration<String> getParameterNames():獲取所有請求的參數名稱
            4. Map<String,String[]> getParameterMap():獲取所有參數的map集合

            * 中文亂碼問題:
                * get方式:tomcat 8 已經將get方式亂碼問題解決了
                * post方式:會亂碼
                    * 解決:在獲取參數前,設置request的編碼request.setCharacterEncoding("utf-8");
        
                
        2. 請求轉發:一種在伺服器內部的資源跳轉方式
            1. 步驟:
                1. 通過request對象獲取請求轉發器對象:RequestDispatcher getRequestDispatcher(String path)
                2. 使用RequestDispatcher對象來進行轉發:forward(ServletRequest request, ServletResponse response) 
            如: request.getRequestDispatcher("/requestDemo9").forward(request,response);

            2. 特點:
                1. 瀏覽器地址欄路徑不發生變化
                2. 只能轉發到當前伺服器內部資源中。
                3. 轉發是一次請求


        3. 共用數據:
            * 域對象:一個有作用範圍的對象,可以在範圍內共用數據
            * request域:代表一次請求的範圍,一般用於請求轉發的多個資源中共用數據
            * 方法:
                1. void setAttribute(String name,Object obj):存儲數據
                2. Object getAttribude(String name):通過鍵獲取值
                3. void removeAttribute(String name):通過鍵移除鍵值對

        4. 獲取ServletContext:
            * ServletContext getServletContext()
        

案例:用戶登錄

* 用戶登錄案例需求:
    1.編寫login.html登錄頁面
        username & password 兩個輸入框
    2.使用Druid資料庫連接池技術,操作mysql,day14資料庫中user表
    3.使用JdbcTemplate技術封裝JDBC
    4.登錄成功跳轉到SuccessServlet展示:登錄成功!用戶名,歡迎您
    5.登錄失敗跳轉到FailServlet展示:登錄失敗,用戶名或密碼錯誤


* 分析

* 開發步驟
    1. 創建項目,導入html頁面,配置文件,jar包
    
    2. 創建資料庫環境
        CREATE DATABASE day14;
        USE day14;
        CREATE TABLE USER(
        
            id INT PRIMARY KEY AUTO_INCREMENT,
            username VARCHAR(32) UNIQUE NOT NULL,
            PASSWORD VARCHAR(32) NOT NULL
        );

    3. 創建包com.ping.domain,創建類User
        package com.ping.domain;
        /**
         * 用戶的實體類
         */
        public class User {
        
            private int id;
            private String username;
            private String password;
        
        
            public int getId() {
                return id;
            }
        
            public void setId(int id) {
                this.id = id;
            }
        
            public String getUsername() {
                return username;
            }
        
            public void setUsername(String username) {
                this.username = username;
            }
        
            public String getPassword() {
                return password;
            }
        
            public void setPassword(String password) {
                this.password = password;
            }
        
            @Override
            public String toString() {
                return "User{" +
                        "id=" + id +
                        ", username='" + username + '\'' +
                        ", password='" + password + '\'' +
                        '}';
            }
        }

    4. 創建包com.ping.util,編寫工具類JDBCUtils
        package com.ping.util;

        import com.alibaba.druid.pool.DruidDataSourceFactory;
        
        import javax.sql.DataSource;
        import javax.xml.crypto.Data;
        import java.io.IOException;
        import java.io.InputStream;
        import java.sql.Connection;
        import java.sql.SQLException;
        import java.util.Properties;
        
        /**
         * JDBC工具類 使用Durid連接池
         */
        public class JDBCUtils {
        
            private static DataSource ds ;
        
            static {
        
                try {
                    //1.載入配置文件
                    Properties pro = new Properties();
                    //使用ClassLoader載入配置文件,獲取位元組輸入流
                    InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
                    pro.load(is);
        
                    //2.初始化連接池對象
                    ds = DruidDataSourceFactory.createDataSource(pro);
        
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        
            /**
             * 獲取連接池對象
             */
            public static DataSource getDataSource(){
                return ds;
            }
        
        
            /**
             * 獲取連接Connection對象
             */
            public static Connection getConnection() throws SQLException {
                return  ds.getConnection();
            }
        }

    5. 創建包com.ping.dao,創建類UserDao,提供login方法
        
        package com.ping.dao;

        import com.ping.domain.User;
        import com.ping.util.JDBCUtils;
        import org.springframework.dao.DataAccessException;
        import org.springframework.jdbc.core.BeanPropertyRowMapper;
        import org.springframework.jdbc.core.JdbcTemplate;
        
        /**
         * 操作資料庫中User表的類
         */
        public class UserDao {
        
            //聲明JDBCTemplate對象共用
            private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        
            /**
             * 登錄方法
             * @param loginUser 只有用戶名和密碼
             * @return user包含用戶全部數據,沒有查詢到,返回null
             */
            public User login(User loginUser){
                try {
                    //1.編寫sql
                    String sql = "select * from user where username = ? and password = ?";
                    //2.調用query方法
                    User user = template.queryForObject(sql,
                            new BeanPropertyRowMapper<User>(User.class),
                            loginUser.getUsername(), loginUser.getPassword());
        
        
                    return user;
                } catch (DataAccessException e) {
                    e.printStackTrace();//記錄日誌
                    return null;
                }
            }
        }
    
    6. 編寫com.ping.web.servlet.LoginServlet類
        package com.ping.web.servlet;

        import com.ping.dao.UserDao;
        import com.ping.domain.User;
        import javax.servlet.ServletException;
        import javax.servlet.annotation.WebServlet;
        import javax.servlet.http.HttpServlet;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.IOException;
        
        
        @WebServlet("/loginServlet")
        public class LoginServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //1.設置編碼
                req.setCharacterEncoding("utf-8");
                //2.獲取請求參數
                String username = req.getParameter("username");
                String password = req.getParameter("password");
                //3.封裝user對象
                User loginUser = new User();
                loginUser.setUsername(username);
                loginUser.setPassword(password);
        
                //4.調用UserDao的login方法
                UserDao dao = new UserDao();
                User user = dao.login(loginUser);
        
                //5.判斷user
                if(user == null){
                    //登錄失敗
                    req.getRequestDispatcher("/failServlet").forward(req,resp);
                }else{
                    //登錄成功
                    //存儲數據
                    req.setAttribute("user",user);
                    //轉發
                    req.getRequestDispatcher("/successServlet").forward(req,resp);
                }
        
            }
            @Override
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                this.doGet(req,resp);
            }
        }

    7. 編寫FailServlet和SuccessServlet類
        @WebServlet("/successServlet")
        public class SuccessServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                //獲取request域中共用的user對象
                User user = (User) request.getAttribute("user");
        
                if(user != null){
                    //給頁面寫一句話
        
                    //設置編碼
                    response.setContentType("text/html;charset=utf-8");
                    //輸出
                    response.getWriter().write("登錄成功!"+user.getUsername()+",歡迎您");
                }
            }       

        @WebServlet("/failServlet")
        public class FailServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                //給頁面寫一句話
        
                //設置編碼
                response.setContentType("text/html;charset=utf-8");
                //輸出
                response.getWriter().write("登錄失敗,用戶名或密碼錯誤");
        
            }
        
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                this.doPost(request,response);
            }
        }

    8. login.html中form表單的action路徑的寫法
        * 虛擬目錄+Servlet的資源路徑

    9. BeanUtils工具類,簡化數據封裝
        * 用於封裝JavaBean的
        1. JavaBean:標準的Java類
            1. 要求:
                1. 類必須被public修飾
                2. 必須提供空參的構造器
                3. 成員變數必須使用private修飾
                4. 提供公共setter和getter方法
            2. 功能:封裝數據


        2. 概念:
            成員變數:
            屬性:setter和getter方法截取後的產物
                例如:getUsername() --> Username--> username


        3. 方法:
            1. setProperty()
            2. getProperty()
            3. populate(Object obj , Map map):將map集合的鍵值對信息,封裝到對應的JavaBean對象中

Response對象

* 功能:設置響應消息
    1. 設置響應行
        1. 格式:HTTP/1.1 200 ok
        2. 設置狀態碼:setStatus(int sc) 
        
    2. 設置響應頭
        setHeader(String name, String value) 
        
    3. 設置響應體
        * 使用步驟
            1. 獲取輸出流
                * 字元輸出流:PrintWriter getWriter()
                * 位元組輸出流:ServletOutputStream getOutputStream()

            2. 使用輸出流,將數據輸出到客戶端瀏覽器


* 案例:
    1. 完成重定向
        * 重定向:資源跳轉的方式
        * 代碼實現:
            //1. 設置狀態碼為302
            response.setStatus(302);
            //2.設置響應頭location
            response.setHeader("location","/day15/responseDemo2");

            //簡單的重定向方法
            response.sendRedirect("/day15/responseDemo2");

        * 重定向的特點:redirect
            1. 地址欄發生變化
            2. 重定向可以訪問其他站點(伺服器)的資源
            3. 重定向是兩次請求,不能使用request對象來共用數據
            
        * 轉發的特點:forward
            1. 轉發地址欄路徑不變
            2. 轉發只能訪問當前伺服器下的資源
            3. 轉發是一次請求,可以使用request對象來共用數據
        
        * forward 和 redirect 區別
            
        * 路徑寫法:
            1. 路徑分類
                1. 相對路徑:通過相對路徑不可以確定唯一資源
                    * 如:./index.html
                    * 不以/開頭,以.開頭路徑

                    * 規則:找到當前資源和目標資源之間的相對位置關係
                        * ./ :當前目錄
                        * ../ :後退一級目錄
                2. 絕對路徑:通過絕對路徑可以確定唯一資源
                    * 如:http://localhost/day15/responseDemo2        /day15/responseDemo2
                    * 以/開頭的路徑

                    * 規則:判斷定義的路徑是給誰用的?判斷請求將來從哪兒發出
                        * 給客戶端瀏覽器使用:需要加虛擬目錄(項目的訪問路徑)
                            * 建議虛擬目錄動態獲取:request.getContextPath()
                            * <a> , <form> 重定向...
                        * 給伺服器使用:不需要加虛擬目錄
                            * 轉發路徑
                            
                    
                    

    2. 伺服器輸出字元數據到瀏覽器
        * 步驟:
            1. 獲取字元輸出流
            2. 輸出數據

        * 註意:
            * 亂碼問題:
                1. PrintWriter pw = response.getWriter();獲取的流的預設編碼是ISO-8859-1
                2. 設置該流的預設編碼
                    response.setCharacterEncoding("utf-8");
                3. 告訴瀏覽器響應體使用的編碼
                    response.setHeader("content-type","text/html;charset=utf-8");
                
                //簡單的形式設置編碼,是在獲取流之前設置(以後使用這種方式設置即可)
                response.setContentType("text/html;charset=utf-8");
                

    3. 伺服器輸出位元組數據到瀏覽器
        * 步驟:
            1. 獲取位元組輸出流
            2. 輸出數據

    4. 驗證碼
        * 本質:圖片
        * 目的:防止惡意表單註冊

    代碼:
        @WebServlet("/checkCodeServlet")
        public class CheckCodeServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                int width = 100;
                int height = 50;
                //1.創建一對象,在記憶體中圖片(驗證碼圖片對象)
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                //2.美化圖片
                //2.1 填充背景色
                Graphics g = image.getGraphics();
                g.setColor(Color.pink);
                g.fillRect(0,0,width,height);
                //2.2 畫邊框
                g.setColor(Color.blue);
                g.drawRect(0,0,width-1,height-1);
        
                String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
                Random ran = new Random();
                for (int i = 1;i <= 4;i++){
                    int index = ran.nextInt(str.length());
                    //獲取字元
                    char ch = str.charAt(index);
                    //2.3 寫驗證碼
                    g.drawString(ch+"", (width / 5) * i,25);
                }
                //2.4 畫干擾線
                g.setColor(Color.green);
                for (int i = 0;i< 10;i++){
                    //隨機生成坐標點
                    int x1 = ran.nextInt(width);
                    int x2 = ran.nextInt(width);
                    int y1 = ran.nextInt(height);
                    int y2 = ran.nextInt(height);
                    g.drawLine(x1,y1,x2,y2);
                }
        
                //3.將圖片輸出到頁面展示
                ImageIO.write(image, "jpg",response.getOutputStream());
            }
            
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                this.doPost(request,response);
            }
        }

    添加點擊圖片或超鏈接切換驗證碼:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script>
            /*
                分析:
                    點擊超鏈接或圖片,需要換一張
                    1.給超鏈接和圖片綁定單擊事件
                    2.重新設置圖片的src屬性值
             */
            window.onload = function () {
                //1.獲取圖片對象
                var img = document.getElementById("checkCode");
                //2.綁定單擊事件
                img.onclick = function () {
                    //加時間戳,解決瀏覽器緩存問題
                    var date = new Date().getTime();
                    img.src = "/day15/checkCodeServlet?"+date;
                }
                a.onclick = function () {
                    var date = new Date().getTime();
                    img.src = "/day15/checkCodeServlet?"+date;
                }
            }
        </script>
    </head>
    <body>
        <img id="checkCode" src="/day15/checkCodeServlet" />
        <a id="change" href="">看不清換一張?</a>
    </body>
    </html>

ServletContext對象:

1. 概念:代表整個web應用,可以和程式的容器(伺服器)來通信

2. 獲取:
    1. 通過request對象獲取
        request.getServletContext();
    2. 通過HttpServlet獲取
        this.getServletContext();

3. 功能:
    1. 獲取MIME類型:
        * MIME類型:在互聯網通信過程中定義的一種文件數據類型
            * 格式: 大類型/小類型   text/html       image/jpeg

        * 獲取:String getMimeType(String file)  
    2. 域對象:共用數據
        1. setAttribute(String name,Object value)
        2. getAttribute(String name)
        3. removeAttribute(String name)

        * ServletContext對象範圍:所有用戶所有請求的數據
    3. 獲取文件的真實(伺服器)路徑
        1. 方法:String getRealPath(String path)  
             String b = context.getRealPath("/b.txt");//web目錄下資源訪問
             System.out.println(b);
    
            String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目錄下的資源訪問
            System.out.println(c);
    
            String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目錄下的資源訪問
            System.out.println(a);

案例:

* 文件下載需求:
    1. 頁面顯示超鏈接
    2. 點擊超鏈接後彈出下載提示框
    3. 完成圖片文件下載


* 分析:
    1. 超鏈接指向的資源如果能夠被瀏覽器解析,則在瀏覽器中展示,如果不能解析,則彈出下載提示框。不滿足需求
    2. 任何資源都必須彈出下載提示框
    3. 使用響應頭設置資源的打開方式:
        * content-disposition:attachment;filename=xxx


* 步驟:
    1. 定義頁面,編輯超鏈接href屬性,指向Servlet,傳遞資源名稱filename
    2. 定義Servlet
        1. 獲取文件名稱
        2. 使用位元組輸入流載入文件進記憶體
        3. 指定response的響應頭: content-disposition:attachment;filename=xxx
        4. 將數據寫出到response輸出流

* 問題:
    * 中文文件問題
        * 解決思路:
            1. 獲取客戶端使用的瀏覽器版本信息
            2. 根據不同的版本信息,設置filename的編碼方式不同

* 代碼:
Servlet:
    @WebServlet(name = "downloadServlet")
    public class DownloadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 獲取請求參數,文件名稱
            String filename = request.getParameter("filename");
            //2.使用位元組輸入流載入文件進記憶體
            //2.1 找到文件伺服器路徑
            ServletContext servletContext = this.getServletContext();
            String realPath = servletContext.getRealPath("/img/"+filename);
            //2.2  用位元組流關聯
            FileInputStream fis = new FileInputStream(realPath);
            //3.設置response的響應頭
            //3.1 設置響應頭類型: content-type
            String mimeType = servletContext.getMimeType(filename);
            response.setHeader("content-type",mimeType);
    
            //解決中文文件名問題
            //1.獲取user-agent請求頭
            String agent = request.getHeader("user-agent");
            //2.使用工具類方法編碼文件名即可
            filename = DownLoadUtils.getFileName(agent, filename);
            
            //3.2 設置響應頭打開方式: content-disposition
            response.setHeader("content-disposition","attachment;filename="+filename);
            //4.將輸入流的數據寫到輸出流中
            ServletOutputStream sos = response.getOutputStream();
            byte[] buff = new byte[1024 * 8];
            int len = 0;
            while((len = fis.read(buff)) != -1){
                sos.write(buff,0,len);
            }
            fis.close();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request,response);
        }
    }


下載工具類:
    import sun.misc.BASE64Encoder;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    
    public class DownLoadUtils {
        public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
            if (agent.contains("MSIE")) {
                // IE瀏覽器
                filename = URLEncoder.encode(filename, "utf-8");
                filename = filename.replace("+", " ");
            } else if (agent.contains("Firefox")) {
                // 火狐瀏覽器
                BASE64Encoder base64Encoder = new BASE64Encoder();
                filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
            } else {
                // 其它瀏覽器
                filename = URLEncoder.encode(filename, "utf-8");
            }
            return filename;
        }
    }

您的分享是我們最大的動力!

更多相關文章
  • 1.設置django的mysql驅動為pymysql 因為django預設的是使用MySqlDb連接mysql資料庫,但是由於該模塊不支持python3.4以上版本,所以使用pymysql模塊 在項目的預設文件夾(也就是settings.py等文件的那個文件夾)的__init__.py文件中增加如下 ...
  • 更新多個對象 例如說我們現在想要將Apress Publisher的名稱由原來的”Apress”更改為”Apress Publishing”。若使用save()方法,如: ? 1 2 3 >>> p = Publisher.objects.get(name='Apress') >>> p.name  ...
  • 最近的Django項目中有複製記錄的需求。資料庫里有一張名為Party的表,記錄用戶創建的party,現在要讓用戶能夠複製一個新的party。本身非常簡單的一個功能,但運行的時候出錯了。我以為是複製過程出錯,所以測試了一下Django中複製記錄可能遇到的情況(後來發現是其他代碼的邏輯出了問題),結果 ...
  • 前言: 公司的產品是一款基於社交的內容聊天軟體,需要集成語音通訊功能,在寫iOS原生項目時,用到的就是Agora SDK,現在寫React Native也直接採用了Agora的庫。 集成iOS、Android的步驟: 請參考鏈接:https://github.com/syanbo/react-nat ...
  • 整理了一些Java方面的架構、面試資料(微服務、集群、分散式、中間件等),有需要的小伙伴可以關註公眾號【程式員內點事】,無套路自行領取 更多優選 "一口氣說出 9種 分散式ID生成方式,面試官有點懵了" "3萬字總結,Mysql優化之精髓" "為了不複製粘貼,我被逼著學會了JAVA爬蟲" "技術部突 ...
  • Nginx 其實就是一款輕量級的 Web 伺服器、反向代理伺服器,由於它的記憶體占用少,啟動極快,高併發能力強,在互聯網項目中廣泛應用。 那麼你可能會問了:“不是說 Nginx 嗎?怎麼又扯出來一個 Web 伺服器呢?啥是伺服器?”。彆著急,在學習 Nginx 之前你還真得知道什麼是伺服器這個概念,下 ...
  • R語言主要用於統計,因此引入了向量這個概念將更好地進行統計計算,在其他無法引入向量的語言當中則會使用迴圈來計算一些大規模的數據,在R語言當中則不需要,下麵我們來看看R語言當中向量的具體用法吧! 首先,如果我們把x作為一個向量,將其賦值為擁有五個元素的向量,代碼如下: > x <- c(1,2,3,4 ...
  • `爬蟲呢有時候數據方便有時候登入獲得cookies,以及獲取他存緩存中的數據` 一.獲取緩存中的數據其實很簡單js註入就好了 ...
一周排行
  • 一:背景 1. 講故事 如果你常翻看FCL的源碼,你會發現這裡面有不少方法藉助了C/C++的力量讓C#更快更強悍,如下所示: [DllImport("QCall", CharSet = CharSet.Unicode)] [SecurityCritical] [SuppressUnmanagedCo ...
  • 上一篇(https://www.cnblogs.com/meowv/p/12966092.html)文章使用AutoMapper來處理對象與對象之間的映射關係,本篇主要圍繞定時任務和數據抓取相關的知識點並結合實際應用,在定時任務中迴圈處理爬蟲任務抓取數據。 開始之前可以刪掉之前測試用的幾個Hello ...
  • 首先創建實體類 1 public class MacState 2 { 3 /// <summary> 4 /// 請求狀態 5 /// </summary> 6 public string success { get; set; } 7 /// <summary> 8 /// 錯誤信息 9 /// ...
  • 0. 前言 前幾天FreeSql的作者向我推薦了FreeSql框架,想讓我幫忙寫個文章介紹一下。嗯,想不到我也能帶個貨了。哈哈,開個玩笑~看了下覺得設計的挺有意思的,所以就謝了這篇文章。 簡單介紹一下,FreeSql 是NCC組織的沙盒級項目,是一款功能強大的 ORM 組件,支持 .NET Core ...
  • 0. 前言 這是一個新的系列,名字是《ASP.NET Core 入門到實戰》。這個系列主講ASP.NET Core MVC,輔助一些前端的基礎知識(能用來實現我們需要的即可,並非主講)。同時這個系列也會在後續介紹ASP.NET Core 平臺的其它類型的項目,並帶領大家以各個類型的項目為主要架構開發 ...
  • 我寫了一個Winform測試程式,用的System.Timers.Timer,在事件里,設置label1.Text,然後,居然句柄泄漏、用戶對象泄漏! 百思不得其解,最後換成System.Windows.Forms.Timer,居然不泄漏了! 最近睡眠不足,哪怕一個很小的問題,隨便搞搞,都半夜了! ...
  • leetcode-7. 整數反轉。 給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。 示例 1: 輸入: 123 輸出: 321 示例 2: 輸入: -123 輸出: -321 示例 3: 輸入: 120 輸出: 21 註意: 假設環境只能存儲得下 32 位的有符號整數,則其 ...
  • 1. Java 虛擬機是什麼? 1.1 虛擬機 虛擬機:虛擬的電腦,一個用來執行虛擬電腦指令的軟體。 虛擬機分為系統虛擬機和程式虛擬機。 系統虛擬機:提供一個可運行完整操作系統的軟體平臺,如 Visual Box、VMware。 程式虛擬機:專門執行單個程式的,典型代表 Java 虛擬機。Jav ...
  • 前言 - strlen 概述 無意間掃到 glibc strlen.c 中代碼, 久久不能忘懷. 在一無所知的編程生涯中又記起點點滴滴: 編程可不是兒戲 ❀, 有些難, 也有些不捨. 隨軌跡一同重溫, 曾經最熟悉的 strlen 手感吧 ~ /* Copyright (C) 1991-2020 Fr ...
  • 背景 隊列[Queue]:是一種限定僅在表頭進行刪除操作,僅在表尾進行插入操作的線性表;即先進先出(FIFO-first in first out):最先插入的元素最先出來。 本文通過編碼實現鏈式隊列類,並模擬一個有趣的應用,能夠幫助我們對鏈式隊列有更深度的理解。 基本概念 結點 每個元素,除了存儲 ...