2014-03-13 124 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

提供一个例子吗? –

相关问题