因此,我正在開發一個Web服務項目。在Java中對PDF進行Base64編碼,在PL/SQL中解碼:不起作用
基本上,它歸結爲:
- PL/SQL邊上傳了一個PDF文件,然後使用Base64編碼文件,然後將其發送到我的休息web服務。
- Java webservice接收文件。我在做任何事情之前保存這個文件(只是爲了測試):如預期的那樣,文件已損壞(這是一個Base64字符串,這是正常的)。
- Java webservice Base64-解碼文件,然後繼續做它需要的文件。在解碼之後,我再次保存文件,並再次按預期工作,並且可以打開並閱讀PDF。
- PL/SQL現在請求重新下載文件。我重新編碼文件並將其發送回請求者。我編碼後保存文件,並按預期(它再次Base64編碼):它不工作(損壞)。
- 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;
你確定你在兩端使用「相同的」Base64表示(特別是填充)嗎? – fge
該問題似乎來自PL/SQL中的解碼部分。你能分享這些嗎? (爲什麼不使用二進制數據傳輸和BLOB,還有一個特別的原因嗎?) –
@fge - 我們試圖檢查它;我知道Java中的commons使用76作爲塊大小,而在PL/SQL中我們使用了48.據我所知,應該沒有什麼區別,對吧? – testuser