因此,我正在开发一个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