使用restTemplate在系統間傳遞(文件)字節數組亂碼問題

base64問題引入

在此之前,問一個問題,什麼是BASE64加解密呢??

計算機中的任何數據都是按照ascii碼存儲的,但是ascii碼的128~255之間的值是不可見字符。而在網絡上交換數據的時候,比如從A地傳到B地,往往要經過多個路由設備。由於不同的設備對字符的處理方式有一些不同,這樣那些不可見字符就有可能被處理錯誤,這樣就不利於傳輸。所以就先把數據先做一個Base64編碼,統統變成可見字符,這樣出錯的可能性就大降低了。

對於證書來說,特別是根證書,一般都是做Base64編碼的,因爲它要在網上被許多人下載,電子郵件的附件一般也作Base64編碼的,因爲一個附件數據往往是有不可見字符的。

那麼Base64到底是怎麼樣編碼的呢?
簡單來說:任何一個數據無非可以看作一個比特流,如01000100010011101100111010111100011001010…,那麼我們取6個比特作爲一組。計算它的ascii值,得到一個字符,這個字符肯定是可見字符,好,把它對應的字符寫出來。再取6個比特,計算,,,如此下去,直到最後,就完成可編碼。

Base64的加密規則

  1. 標準Base64只有64個字符(英文大小寫,數字,和+,/)以及用作後綴等號;
  2. base64是把3個字節變成4個可打印的字符,所以base64編碼後的字符一定能被4整除(不算用作後綴的等號。
  3. 等號一定用作後綴),且數目一定是0個,1個或2個。這是因爲如果原文長度不能被3整除,base64要在後面添加\0,湊齊3n。爲了正確還原,添加了幾個\n就加上了幾個等號。顯然添加等號的數目只能是0,1,2
  4. 嚴格來說,base64不能算是一種加密,只能說是編碼轉換。使用base64的初衷,是爲了方便把含有不可見字符串的信息用可見字符串表示出來,以便複製粘貼。

一個Base64的應用場景

提供一個工作中用到過的base64場景
一個xml當中包含另一個xml數據,此時如果將xml數據直接寫入顯然不合適,將xml進行適當編碼存入較爲方便,事實上xml當中的字符一般都是可見字符(0-127之間),但是由於中文的存在,可能存在不可見字符,直接將字符打印在外層xml的數據中顯然不合理,那麼怎麼辦呢?
可以使用base64進行編碼,然後存入xml,解碼反之
其實還有個辦法,將byte的值寫在xml當中,空格或者,分開,這樣也可以將byte數據傳入,不過這樣更浪費空間,並且不易保存.

另一個,比如http協議當中的key value字段,必須進行URLEncode 不然出現的等號可能使解析失敗 空格也會使http請求解析出現問題,比如 請求行就是以空格來劃分的 POST /guowuxin/hehe HTTP/1.1

又比如有些文本協議不支持不可見字符的傳遞,只能用大於32的可見字符來傳遞信息(協議規定)

在工作中遇到的字節數組在系統之間傳遞的問題。

package com.zhangqi.servlet;

public class DownLoadTest {

    RequestMapping(value ="/sdbDownLoadAttachment", method =RequestMethod.POST)

    public Object sdbDownLoadAttachment(@RequestBody String paramStr, HttpServletResponse response, HttpServletRequest request) throws IOException {
        LogUtil.info("sdbDeleteAttachment:" + paramStr);
        Map<String, Object> paramMap = (Map<String, Object>) JSONObject.parse(paramStr);
        String key = (String) paramMap.get("key");
        Response iobsResponse = sdbaoUploadIobsServiceImpl.downLoadAttachment(key);
        if (iobsResponse.isOK()) {
            try (InputStream ins = iobsResponse.downloadFileStream()) {
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] bytes = new byte[1024];
                int length = 1;
                while ((length = ins.read(bytes)) != -1) {
                    byteArrayOutputStream.write(bytes, 0, length);

                }
                byte[] bytes2 = byteArrayOutputStream.toByteArray();
                BASE64Encoder base64Encoder = new BASE64Encoder();
                String encode = base64Encoder.encode(bytes2);
                HashMap<String, Object> resultMap1 = Maps.newHashMap();
                resultMap1.put("byte", bytes2);
                return resultMap1;

            } catch (IOException e) {
                LogUtil.error(e, "文件流異常");
            }
        } else {
            return new ResponseResult.ResponseBuilder().builderResponseCode(EnumForSaleBaseResult.CODE_800000.getResultCode()).builderResponseMsg("失敗" + "錯誤碼爲:" + iobsResponse.code() + "錯誤信息爲:"
                    + iobsResponse.error()).build();
        }
        return null;
    }
}

 @RestController
    public class DownLoadTest {
        @RequestMapping("/testDownload")
        public void testDownload(@RequestBody String param) throws Exception {
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/json;charset=utf-8");
            headers.set("Accept", "application/json;charset=UTF-8");
            HttpEntity entity = new HttpEntity(param, headers);
            ResponseEntity<Map> exchange = restTemplate.exchange("http://localhost:44631/accidentGroup/sdbDownLoadAttachment", HttpMethod.POST, entity, Map.class);
            Map body = exchange.getBody();
            String aByte2 = (String) body.get("byte");
            System.out.println(aByte2.getClass());
            BASE64Decoder base64Decoder = new BASE64Decoder();
            base64Decoder.decodeBuffer(aByte2) byte[] bytes3 = aByte2.getBytes();
            byte[] aByte = (byte[]) body.get("byte");
            FileOutputStream fileOutputStream = new FileOutputStream(new File("D://a.xls"));
            fileOutputStream.write(aByte, 0, aByte.length);
            fileOutputStream.flush();
            fileOutputStream.close();
        }
    }

在這裏記錄一下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章