2014-03-13 120 views
0

因此,我正在開發一個Web服務項目。在Java中對PDF進行Base64編碼,在PL/SQL中解碼:不起作用

基本上,它歸結爲:

  1. PL/SQL邊上傳了一個PDF文件,然後使用Base64編碼文件,然後將其發送到我的休息web服務。
  2. Java webservice接收文件。我在做任何事情之前保存這個文件(只是爲了測試):如預期的那樣,文件已損壞(這是一個Base64字符串,這是正常的)。
  3. Java webservice Base64-解碼文件,然後繼續做它需要的文件。在解碼之後,我再次保存文件,並再次按預期工作,並且可以打開並閱讀PDF。
  4. PL/SQL現在請求重新下載文件。我重新編碼文件並將其發送回請求者。我編碼後保存文件,並按預期(它再次Base64編碼):它不工作(損壞)。
  5. PL/SQL收到文件,Base64-解碼文件並嘗試打開它... Bam,損壞,無法讀取文件。

通信之間可能有些問題:它是Java中的Base64編碼,PL/SQL中的Base64解碼。你會懷疑它沒有區別,因爲它使用的是標準(我猜Base64是標準的,對吧?)。

我們嘗試了兩種選擇:在使用Java對PDF進行重新編碼之後,我嘗試再次對其進行重新解碼並保存;這個文件是正確的,我可以閱讀PDF。所以我們假設Java中的編碼是正確的。我們在PL/SQL中也嘗試過 - 上傳BLOB,編碼到Base64,解碼,下載並打開。這也適用。所以我們假設PL/SQL中的編碼和解碼部分也起作用。

奇怪的是,我可以使用Base64對PL/SQL中的文件進行編碼,然後使用Java將其解碼,然後保存並讀取它。當我用Java對文件進行重新編碼並嘗試在PL/SQL中進行解碼時,它只會出錯。這對我來說聽起來好像在PL/SQL中使用的標準 - Java之間不存在問題,因爲那麼第一步也會失敗。

我們使用Java中的公共庫(org.apache.commons.codec.binary.Base64)。在PL/SQL中,我們嘗試使用UTL包,定製方法,Java存儲過程以及Apex_webservice(apex_web_service.blob2clobbase64(p_blob)apex_web_service.clobbase642blob(p_clob))。他們都給出了相同的結果。

我們正在慢慢失去想法。有沒有人有另一個更好的主意?

謝謝!

---編輯---

這是文件是如何在PL/SQL解碼:

FUNCTION encode_base64 (p_blob_in IN BLOB) 
    RETURN CLOB IS 
     v_clob    CLOB; 
     v_result   CLOB; 
     v_offset   INTEGER; 
     v_chunk_size  BINARY_INTEGER := (48/4) * 3; 
     v_buffer_varchar VARCHAR2 (48); 
     v_buffer_raw  RAW (48); 
    BEGIN 
     IF p_blob_in IS NULL THEN 
      RETURN NULL; 
     END IF; 
     DBMS_LOB.createtemporary (v_clob, TRUE); 
     v_offset := 1; 
     FOR i IN 1 .. CEIL (DBMS_LOB.getlength (p_blob_in)/v_chunk_size) LOOP 
      DBMS_LOB.read (p_blob_in, v_chunk_size, v_offset, v_buffer_raw); 
      v_buffer_raw := UTL_ENCODE.base64_encode (v_buffer_raw); 
      v_buffer_varchar := UTL_RAW.cast_to_varchar2 (v_buffer_raw); 
      DBMS_LOB.writeappend (v_clob, LENGTH (v_buffer_varchar), v_buffer_varchar); 
      v_offset := v_offset + v_chunk_size; 
     END LOOP; 
     v_result := v_clob; 
     DBMS_LOB.freetemporary (v_clob); 
     RETURN v_result; 
END encode_base64; 

這是該文件如何在Java編碼:

byte[] content = /*Here is my content in bytes. Before encoding, when I save, this is correct*/ 
Base64.encodeBase64String(content); 

---編輯2 ---

我意外地在上面的PL/SQL中添加了解碼部分。這是PL/SQL中的編碼部分。

function decode_base64(p_clob_in in clob) return blob is 
    v_blob blob; 
    v_result blob; 
    v_offset integer; 
    v_buffer_size binary_integer := 48; 
    v_buffer_varchar varchar2(48); 
    v_buffer_raw raw(48); 
    begin 
     if p_clob_in is null then 
      return null; 
     end if; 
     dbms_lob.createtemporary(v_blob, true); 
     v_offset := 1; 
     for i in 1 .. ceil(dbms_lob.getlength(p_clob_in)/v_buffer_size) loop 
      dbms_lob.read(p_clob_in, v_buffer_size, v_offset, v_buffer_varchar); 
      v_buffer_raw := utl_raw.cast_to_raw(v_buffer_varchar); 
      v_buffer_raw := utl_encode.base64_decode(v_buffer_raw); 
      dbms_lob.writeappend(v_blob, utl_raw.length(v_buffer_raw), v_buffer_raw); 
      v_offset := v_offset + v_buffer_size; 
     end loop; 
     v_result := v_blob; 
     dbms_lob.freetemporary(v_blob); 
     return v_result; 
end decode_base64; 
+0

你確定你在兩端使用「相同的」Base64表示(特別是填充)嗎? – fge

+0

該問題似乎來自PL/SQL中的解碼部分。你能分享這些嗎? (爲什麼不使用二進制數據傳輸和BLOB,還有一個特別的原因嗎?) –

+0

@fge - 我們試圖檢查它;我知道Java中的commons使用76作爲塊大小,而在PL/SQL中我們使用了48.據我所知,應該沒有什麼區別,對吧? – testuser

回答

1

大部分這類問題都來自小東西......

到底發生了什麼?我將Base64-String發送回XML中。在PL/SQL中,我們將該字符串解壓縮爲clob,然後再解碼爲blob。

我們打印並檢查了字符串......這是正確的。

當我們試圖檢查從PL/SQL發送的clob與我們在PL/SQL中返回的clob之間的區別時,發現char(10)& char(13) - linebreaks,本質上。不可見的眼睛,但使clob(和解碼blob)腐敗。翻譯功能讓這些功能得到了發揮,現在它成爲一種魅力。

感謝您的幫助!

+0

所以你得到XML內的base64字符串,然後將其提取到CLOB。你可以直接將提取到BLOB中嗎?我懷疑CLOB可能會「幫助」將它認爲是從Unix到DOS樣式的換行符的字符轉換,反之亦然。只是一個想法。分享並享受。 –

+0

問題是我們需要將CLOB從XML中提取出來之後才能Base64解碼它(回到BLOB)。解碼函數假定IN參數是CLOB,OUT參數是BLOB。所以在我看來,這將是一個解決方法(我承認,翻譯現在也是一個解決方法) – testuser

+0

提供一個例子嗎? –

相關問題