2025-07-08

HTTP協議上的GZIP編碼是一種用來改進WEB應用程序性能的技術。大流量的WEB站點常常使用GZIP壓縮技術來減少文件大小,減少文件大小有兩個明顯的好處,一是可以減少存儲空間,二是通過網絡傳輸文件時,可以減少傳輸的時間。作者在寫這篇博客時經過測試,4.4MB的文本數據經過Gzip傳輸到客戶端之後變為392KB,壓縮效率極高。

一.服務端

服務端有2種方式去壓縮,一種可以自己壓縮,但是更推薦第二種方式,用PrintWriter作為輸出流,工具類代碼如下

/** 

         * 判斷瀏覽器是否支持 gzip 壓縮 

         * @param req 

         * @return boolean 值 

         */  

        public static boolean isGzipSupport(HttpServletRequest req) {  

            String headEncoding = req.getHeader("accept-encoding");  

            if (headEncoding == null || (headEncoding.indexOf("gzip") == -1)) { // 客戶端 不支持 gzip  

                return false;  

            } else { // 支持 gzip 壓縮  

                return true;  

            }  

        }  

  

        /** 

         * 創建 以 gzip 格式 輸出的 PrintWriter 對象,如果瀏覽器不支持 gzip 格式,則創建普通的 PrintWriter 對象, 

         * @param req 

         * @param resp 

         * @return 

         * @throws IOException 

         */  

        public static PrintWriter createGzipPw(HttpServletRequest req, HttpServletResponse resp) throws IOException {  

            PrintWriter pw = null;  

            if (isGzipSupport(req)) { // 支持 gzip 壓縮  

                pw = new PrintWriter(new GZIPOutputStream(resp.getOutputStream()));  

                // 在 header 中設置返回類型為 gzip  

                resp.setHeader("content-encoding", "gzip");  

            } else { // // 客戶端 不支持 gzip  

                pw = resp.getWriter();  

            }  

            return pw;  

        }  

      

servlet代碼如下:

public void doPost(HttpServletRequest request, HttpServletResponse response)  

        throws ServletException, IOException {  

    response.setCharacterEncoding("utf-8");  

    response.setHeader("Content-Encoding", "gzip");  

    String ret = "{\"ContentLayer\":{\"title\":\"內容層\"},\"PageLink\":{\"title\":\"頁面跳轉\"},\"WebBrowser\":{\"title\":\"瀏覽器\"},"  

            + "\"InlinePage\":{\"title\":\"內嵌頁面\"},\"VideoComp\":{\"title\":\"視頻\"},"  

            + "\"PopButton\":{\"title\":\"內容開關\"},\"ZoomingPic\":{\"title\":\"縮放大圖\"},"  

            + "\"Rotate360\":{\"title\":\"360度旋轉\"}}";  

      

    PrintWriter pw = new PrintWriter(new GZIPOutputStream(response.getOutputStream()));  

    pw.write(ret);  

    pw.close();  

}  

  

public void doGet(HttpServletRequest request, HttpServletResponse response)  

        throws ServletException, IOException {  

    this.doPost(request, response);  

}  

在代理軟件中跟蹤到的數據如下:

‹«VrÎÏ+IÍ+ñI¬L-R²ªV*É,ÉIU²R:rëÄÝM•ju”ÓS}2ó²‘e/m>üìÌë«@òá©INEùåŨúŸ¬?pàØw¼g^Nf^*ÈTóo™R–™’šïœŸ[€¬àÔåc[ÁÖç8•–”äç¡»nÿª7@  

¢òós3óÒ2“‘Uœþºýè–Ïg&pide;€Tå—$–¤› +r·¸ðä‡Zh¤†ˆ  

 

實際數據如下:

{"ContentLayer":{"title":"內容層"},"PageLink":{"title":"頁面跳轉"},"WebBrowser":{"title":"瀏覽器"},"InlinePage":{"title":"內嵌頁面"},"VideoComp":{"title":"視頻"},"PopButton":{"title":"內容開關"},"ZoomingPic":{"title":"縮放大圖"},"Rotate360":{"title":"360度旋轉"}}  

 

二.Android客戶端

得到HttpClient代碼:

private static DefaultHttpClient getHttpClient() {  

        DefaultHttpClient httpClient = new DefaultHttpClient();  

  

        // 設置 連接超時時間  

        httpClient.getParams().setParameter(  

                HttpConnectionParams.CONNECTION_TIMEOUT, TIMEOUT_CONNECTION);  

        // 設置 讀數據超時時間  

        httpClient.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT,  

                TIMEOUT_SOCKET);  

        // 設置 字符集  

        httpClient.getParams().setParameter("http.protocol.content-charset",  

                UTF_8);  

        return httpClient;  

    }  

 

得到HttpPost:

private static HttpPost getHttpPost(String url) {  

        HttpPost httpPost = new HttpPost(url);  

        // 設置 請求超時時間  

        httpPost.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT,  

                TIMEOUT_SOCKET);  

        httpPost.setHeader("Connection", "Keep-Alive");  

        httpPost.addHeader("Accept-Encoding", "gzip");  

        return httpPost;  

    }  

 

訪問網絡代碼:

public static InputStream http_post_return_byte(String url,  

            Map<String, String> params) throws AppException {  

        DefaultHttpClient httpclient = null;  

        HttpPost post = null;  

        HttpResponse response = null;  

        StringBuilder sb = null;  

        StringEntity stringEntity = null;  

        try {  

            httpclient = getHttpClient();  

            post = getHttpPost(url);  

            sb = new StringBuilder();  

            if (params != null && !params.isEmpty()) {  

                Logger.d("In http_post the url is get here");  

                for (Entry<String, String> entry : params.entrySet()) {  

                    sb.append(entry.getKey())  

                            .append("=")  

                            .append(URLEncoder.encode(entry.getValue(),  

                                    HTTP.UTF_8)).append("&");  

                }  

                sb.deleteCharAt(sb.lastIndexOf("&"));  

                Logger.d("In http_post the url is " + url + " and params is "  

                        + sb.toString());  

                stringEntity = new StringEntity(sb.toString());  

                stringEntity  

                        .setContentType("application/x-www-form-urlencoded");  

                post.setEntity(stringEntity);  

            }  

  

            response = httpclient.execute(post);  

            int statusCode = response.getStatusLine().getStatusCode();  

            Logger.d("statusCode is " + statusCode);  

            if (statusCode != HttpStatus.SC_OK) {  

                throw AppException.http(statusCode);  

            }  

  

            InputStream is = response.getEntity().getContent();  

  

            Header contentEncoding = response  

                    .getFirstHeader("Content-Encoding");  

            if (contentEncoding != null  

                    && contentEncoding.getValue().equalsIgnoreCase("gzip")) {  

                is = new GZIPInputStream(new BufferedInputStream(is));  

            }  

            return is;  

  

        } catch (ClientProtocolException e) {  

            e.printStackTrace();  

            throw AppException.http(e);  

        } catch (IOException e) {  

            e.printStackTrace();  

            throw AppException.network(e);  

        } finally {  

  

            /* 

             * if (!post.isAborted()) { 

             *  

             * post.abort(); } httpclient = null; 

             */  

  

        }  

  

    }  

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *