天天看點

SpringMVC傳回json是設定編輯等消息頭,消息頭資訊介紹(respone.setHeader,這個從網上擷取)

1、  springmvc中設定消息頭,例子如下:

@requestmapping(value="/hasoperateprivilege")

@responsebody

public map<string, object> hasoperateprivilege(httpservletrequest request,

         httpservletresponse response,string websiteid) {

   map<string,object> parammap = new hashmap<string,object>();

   //設定消息頭資訊

   setresponeinfo(response);

   try {

      //用以辨別是否有操作的權限

      string hasoperateprivilege = templateservice.hasoperateprivilege(getsessionuserid(request),websiteid);

      parammap.put("flag", "success");

      parammap.put("info",hasoperateprivilege);

   } catch (exception e) {

      parammap.put("flag", "error");

      e.printstacktrace();

   }

   return parammap;

}

其中setresponeinfo(response);的内容如下:

/**

 * 設定response的時候傳回的消息頭資訊 

 * @param response

 * @attention隻需要傳遞竟來一個response就可以了

 * @author toto

 * @date 2016-5-16

 * @note  begin modify by 塗作權 2016-05-16 原始建立

 */

protected void setresponeinfo(httpservletresponse response) {

   //下面的表示以普通文本的方式解析

   response.setcontenttype("text/plain;charset=utf-8");

   response.reset();

   response.setheader("expires", "-1");

2、其它相關說明:

response.setheader()下載下傳中文檔案名亂碼問題收藏  1.http消息頭

(1)通用資訊頭

即能用于請求消息中,也能用于響應資訊中,但與被傳輸的實體内容沒有關系的資訊頭,如data,pragma

主要:cache-control , connection , data , pragma , trailer , transfer-encoding ,upgrade

(2)請求頭

用于在請求消息中向伺服器傳遞附加資訊,主要包括客戶機可以接受的資料類型,壓縮方法,語言,以及客戶計算機上保留的資訊和發出該請求的超連結源位址等.

主要: accept, accept-encoding , accept-language , host ,

(3)響應頭

用于在響應消息中向用戶端傳遞附加資訊,包括服務程式的名稱,要求用戶端進行認證的方式,請求的資源已移動到新位址等.

主要:location , server , www-authenticate(認證頭)

(4)實體頭

用做實體内容的元資訊,描述了實體内容的屬性,包括實體資訊的類型,長度,壓縮方法,最後一次修改的時間和資料的有效期等.

主要:content-encoding , content-language , content-length , content-location ,content-type

(4)擴充頭

主要:refresh,content-disposition

2. 幾個主要頭的作用

(1)content-type的作用

該實體頭的作用是讓伺服器告訴浏覽器它發送的資料屬于什麼檔案類型。

例如:當content-type 的值設定為text/html和text/plain時,前者會讓浏覽器把接收到的實體内容以html格式解析,後者會讓浏覽器以普通文本解析.

(2)content-disposition 的作用

當content-type的類型為要下載下傳的類型時, 這個資訊頭會告訴浏覽器這個檔案的名字和類型。

在講解這個内容時,張老師同時講出了解決中文檔案名亂碼的解決方法,平常想的是使用getbytes(), 實際上應使用email的附件名編碼方法對檔案名進行編碼,但ie不支援這種作法(其它浏覽器支援) , 使用javax.mail.internet.*包的mimeutility.encodeword("中文.txt")的方法進行編碼。

content-disposition擴充頭的例子:

<%@ pagepageencoding="gbk" contenttype="text/html;charset=utf-8"import="java.util.*,java.text.*" %>

<%=dateformat.getdatetimeinstance(dateformat.short,dateformat.short, locale.china).format(new date())

%>

<%

              response.setheader("content-type","video/x-msvideo");

              response.setheader("content-disposition","attachment;filename=aaa.doc");

content-disposition中指定的類型是檔案的擴充名,并且彈出的下載下傳對話框中的檔案類型圖檔是按照檔案的擴充名顯示的,點儲存後,檔案以filename的值命名,儲存類型以content中設定的為準。

注意:在設定content-disposition頭字段之前,一定要設定content-type頭字段。

(3)authorization頭的作用

authorization的作用是當用戶端通路受密碼保護時,伺服器端會發送401狀态碼和www-authenticate響應頭,要求客戶機使用authorization來應答。

例如:

response.setstatus(401);

response.setheader("www-authenticate","basic realm=/"tomcat manager application/"");

3.如何實作檔案下載下傳

要實作檔案下載下傳,我們隻需要設定兩個特殊的相應頭,它們是什麼頭?如果檔案名帶中文,該如何解決?

兩個特殊的相應頭:

----content-type:      application/octet-stream

----content-disposition:attachment;filename=aaa.zip

response.setcontenttype("image/jpeg");response.setheader("content-disposition","attachment;filename=bluehills.jpg");

如果檔案中filename參數中有中文,則就會出現亂碼。

解決辦法:

(1)mimeutility.encodeword("中文.txt");//現在版本的ie還不行

(2)newstring("中文".getbytes("gb2312"),"iso8859-1");//實際上這個是錯誤的

4. 測試并分析檔案名亂碼問題

response.setheader()下載下傳中文檔案名亂碼問題

response.setheader("content-disposition","attachment; filename=" + java.net.urlencoder.encode(filename,"utf-8"));

下載下傳的程式裡有了上面一句,一般在ie6的下載下傳提示框上将正确顯示檔案的名字,無論是簡體中文,還是日文。不過當時确實沒有仔細測試檔案名為很長的中文檔案名的情況。現如今經過仔細測試,發現文字隻要超過17個字,就不能下載下傳了。分析如下:

一. 通過原來的方式,也就是先用urlencoder編碼,當中文文字超過17個時,ie6 無法下載下傳檔案。這是ie的bug,參見微軟的知識庫文章 kb816868。原因可能是ie在處理 responseheader 的時候,對header的長度限制在150位元組左右。而一個漢字編碼成utf-8是9個位元組,那麼17個字便是153個位元組,是以會報錯。而且不跟字尾也不對.

二. 解決方案:将檔案名編碼成iso8859-1是有效的解決方案,代碼如下:

response.setheader("content-disposition", "attachment;filename=" + new string(filename.getbytes("gb2312"), "iso8859-1" ) );

在確定附件檔案名都是簡體中文字的情況下,那麼這個辦法确實是最有效的,不用讓客戶逐個的更新ie。如果台灣同胞用,把gb2312改成big5就行。但現在的系統通常都加入了國際化的支援,普遍使用utf-8。如果檔案名中又有簡體中文字,又有繁體中文,還有日文。那麼亂碼便産生了。另外,在上firefox(v1.0-en)下載下傳也是亂碼。

三. 參看郵件中的中文附件名的形式,用outlook建立一個帶有中文附件的郵件,然後看這個郵件的源代碼,找到:

content-disposition:attachment;

filename="=?gb2312?b?0mk9qcdoxlg+zss1ts50ehq=?="

用這個filename原理上就可以顯示中文名附件,但是現在ie并不支援,firefox是支援的。嘗試使用 javamail的mimeutility.encode()方法來編碼檔案名,也就是編碼成=?gb2312?b?xxxxxxxx?= 這樣的形式,并從rfc1522 中找到對應的标準支援。

折中考慮,結合了一、二的方式,代碼片斷如下:

stringfilename = urlencoder.encode(atta.getfilename(), "utf-8");

/*

*/

if (filename.length() > 150) {

stringguesscharset = xxxx

//根據request的locale 得出可能的編碼,中文作業系統通常是gb2312

filename= new string(atta.getfilename().getbytes(guesscharset), "iso8859-1");

response.setheader("content-disposition","attachment; filename=" + filename);

編碼轉換的原理:

首先在源程式中将編碼設定成gb2312字元編碼,然後将源程式按unicode編碼轉換成位元組碼加載到記憶體中(java加載到記憶體中的位元組碼都是unicode編碼),然後按gb2312編碼獲得中文字元串的位元組數組,然後生成按iso8859-1編碼形式的unicode字元串(這時的4個位元組就變成了8個位元組,高位位元組補零),

當在網絡中傳輸時,因為setheader方法中的字元隻能按iso8859-1傳輸,是以這時候就又把unicode字元轉換成了iso8859-1的編碼傳到浏覽器(就是把剛才高位補的零全去掉),這時浏覽器接收到的iso8859-1碼的字元因為符合gb2312編碼,是以就可以顯示中文了。

5. jsp翻譯成class時的編碼問題

記事本中代碼塊1:

<%=

      "a中文".length()

代碼塊2:

<%@ pagepageencoding="gbk"%>

為什麼上面的輸出值為5,改成下面的則輸出3?

因為上面的代碼沒有添加該檔案的編碼說明 , web應用程式在将jsp翻譯成class檔案時 , 把該字元串的内容按預設的儲存方式指定的編碼ascii碼來算的,在utf-8中,原ascii字元占一個位元組,漢字占兩個位元組,對應兩個字元,長度就變成了5, 而下面的是gbk編碼, 一個漢字和一個英文都對應一個字元,得到結果就為3.

response.setheader(...)檔案名中有空格的時候

string filename = stringutils.trim(file.getname());

string formatfilename =encodingfilename(name);//在後面定義方法encodingfilename(stringfilename);

response.setheader("content-disposition","attachment; filename=" + formatfilename );

//處理檔案名中出現的空格  

//其中%20是空格在utf-8下的編碼

public static stringencodingfilename(string filename) {        

     stringreturnfilename = "";        

     try {           

        returnfilename= urlencoder.encode(filename, "utf-8");           

        returnfilename= stringutils.replace(returnfilename, "+", "%20");           

        if(returnfilename.length() > 150) {               

              returnfilename= new string(filename.getbytes("gb2312"), "iso8859-1");               

              returnfilename= stringutils.replace(returnfilename, " ", "%20");           

         }       

    } catch (unsupportedencodingexception e) {           

        e.printstacktrace();           

        if (log.iswarnenabled()) {               

               log.info("don't support this encoding ...");           

        }        

    }        

    return returnfilename;