0

我有一个存储在 PL/SQL blob 变量中的有效文件attachment_blob_。假设文件的大小足够小,以下过程可将文件附加到电子邮件中。

PROCEDURE Write_Mail_Attachment IS BEGIN
    Write_Part_Boundary (OUTER_BOUNDARY_);
    utl_smtp.write_data (
        smtp_conn_,
        'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; ' ||
        'name="' || attachment_name_ || '"' || utl_tcp.crlf ||
        'Content-Transfer-Encoding: base64' || utl_tcp.crlf ||
        'Content-Disposition: attachment;filename="'||attachment_name_||'"'||utl_tcp.crlf||utl_tcp.crlf
    );
    utl_smtp.write_raw_data (smtp_conn_, utl_encode.base64_encode(attachment_blob_));
END Write_Mail_Attachment;

(只是为了避免歧义或“你检查过这个”类型的答案,所有变量都是有效的。任何未在此块中定义的变量都属于父范围。)

当变量attachment_blob_大于某个大小时,我的问题就开始了。它变得太大而无法由utl_encode.base64_encode()函数处理,并产生数字或值错误。

好吧,没关系,我告诉自己。我需要做的就是把blob它分成多个块。所以我修改程序如下:

PROCEDURE Write_Mail_Attachment IS
    chunk_size_    NUMBER := 1900;
    offset_        NUMBER := 1;
    file_chunk_    RAW(1900);
BEGIN
    Write_Part_Boundary (OUTER_BOUNDARY_);
    utl_smtp.write_data (
        smtp_conn_,
        'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; ' ||
        'name="' || attachment_name_ || '"' || utl_tcp.crlf ||
        'Content-Transfer-Encoding: base64' || utl_tcp.crlf ||
        'Content-Disposition: attachment; filename="'||attachment_name_||'"'||utl_tcp.crlf||utl_tcp.crlf
    );
    WHILE offset_ < Dbms_Lob.GetLength(attachment_blob_) LOOP
        Dbms_Lob.Read (attachment_blob_, chunk_size_, offset_, file_chunk_);
        utl_smtp.write_raw_data (smtp_conn_, utl_encode.base64_encode(file_chunk_));
        offset_ := offset_ + chunk_size_;
    END LOOP;
END Write_Mail_Attachment;

所以现在,这个过程没有错误地执行,因为块大小永远不会变得太大而utl_encode.base64_encode()无法管理。但现在的问题是附件到达我的收件箱时已损坏。

当我调查“原始”电子邮件内容时,我可以看到附件内容字符串被修剪为大约 1900 个字符。如果我将block_size_变量定义为50(而不是1900),则电子邮件中的原始内容将被截断为大约 50 个字符。换句话说,就好像该过程utl_smtp.write_raw_data()在循环的每次迭代中都覆盖了文件内容的前一部分,所以我只会在发送电子邮件时得到文件中的最后一块。

我已经验证了 上的文档utl_smtp.write_raw_data(),该文档确认电子邮件将被附加到,而不是覆盖最后一个块。

我还搜索了 Oracle 留言板的解决方案,(实际上,我上面的第二个过程来自我在那里找到的一些帖子)。但是,我还不能完整地发送附件。

有人可以看到我做错了什么吗?

4

1 回答 1

1

您必须记住,Base64 将 3 个字节编码为 4 个字节,并在最后一组包含少于 3 个字节时使用“=”,请检查Wikipedia上的填充部分。字符“=”只能放在编码文档的末尾。这就是为什么你的缓冲区长度必须是三的倍数。

于 2013-08-31T18:29:09.593 回答