#oracle #plsql #smtp #plsqldeveloper
#Oracle #plsql #smtp #plsqldeveloper
Вопрос:
у нас есть таблица с файлами, сохраненными в виде большого двоичного объекта
Я пишу код, который отправляет эти файлы по электронной почте в виде вложения!
пока все работает нормально, но файлы (EXCEL, PDF, … что когда-либо) не читаются программами, открываются только текстовые файлы и Excel, но после некоторого сообщения об ошибке, когда все PDF-файлы вообще не открываются!
вот часть кода, о которой идет речь!
utl_smtp.write_data( l_connection, '--'|| l_boundary || utl_tcp.crlf);
utl_smtp.write_data( l_connection, 'Content-Type: application/octet-stream' || utl_tcp.crlf);
utl_smtp.write_data( l_connection, 'Content-Disposition: attachment; filename="' || V_NAME || '"' || utl_tcp.crlf);
utl_smtp.write_data( l_connection, 'Content-Transfer-Encoding: base64' || utl_tcp.crlf );
utl_smtp.write_data( l_connection, utl_tcp.crlf );
v_length := dbms_lob.getlength(V_BLOB_CONTENT);
while v_offset < v_length loop
dbms_lob.read( V(i).BLOB_CONTENT, v_buffer_size, v_offset, v_raw );
utl_smtp.write_raw_data( l_connection, utl_encode.base64_encode(v_raw) );
utl_smtp.write_data( l_connection, utl_tcp.crlf );
v_offset := v_offset v_buffer_size;
end loop while_loop;
utl_smtp.write_data( l_connection, utl_tcp.crlf );
есть предложения?
Ответ №1:
вот процедура, которую я использую именно для этого
PROCEDURE StreamAttachmentToConn( p_conn IN OUT utl_smtp.connection
,p_boundary IN raw
,p_FileName IN VARCHAR2
,p_FileData IN BLOB) PARALLEL_ENABLE
AS
l_len integer := 0 ;
l_idx integer := 1 ;
l_buff_size integer := 57 ;
l_raw raw(57) ;
BEGIN
-- Attachment
utl_smtp.write_data( p_conn, '--' || p_boundary || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Type: application/octet-stream' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Disposition: attachment; ' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, ' filename="' || p_FileName || '"' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, 'Content-Transfer-Encoding: base64' || utl_tcp.crlf );
utl_smtp.write_data( p_conn, utl_tcp.crlf );
-- Loop through the blob
-- chuck it up into 57-byte pieces
-- and base64 encode it and write it into the mail buffer
l_len := dbms_lob.getlength(p_FileData);
-- force reinit on this may change
l_buff_size := 57 ;
l_idx := 1;
while l_idx < l_len loop
dbms_lob.read( p_FileData , l_buff_size, l_idx, l_raw );
utl_smtp.write_raw_data( p_conn, utl_encode.base64_encode(l_raw) );
utl_smtp.write_data( p_conn, utl_tcp.crlf );
l_idx := l_idx l_buff_size;
end loop;
END StreamAttachmentToConn;
Я использую это для добавления нескольких вложений в одно электронное письмо. для меня это работает как чемпион.
одна вещь, p_boundary передается как
l_boundary raw(32) := sys_guid();
Я вижу, что у вас уже есть l_boundary, и это то, что вы должны использовать.
это основано на http://christopherbeck.wordpress.com/category/plsql/ а также http://www.oracle-base.com/articles/misc/EmailFromOraclePLSQL.php#attachment
.
затем в вашем коде просто передайте ваше smtp-соединение, l_boundary (т. Е. Необработанный sys_guid или что бы вы ни использовали), имя файла (как оно будет отображаться во вложении электронного письма) и большой двоичный объект.
*РЕДАКТИРОВАТЬ —> дополнительная информация *
У нас то же самое с предположением о:
—> предположим, что v_offset начинается с 1 -> v_buffer_size предположим, 57
Но я заметил, что есть порядок, которому вы должны следовать, чтобы заставить его работать (в частности, поместите вложения рядом с КОНЦОМ после тела!!!
- ЛОГИКА подключения
- добавьте всех получателей
- ЛОГИКА заголовка: «ОТ», тема
- Основная логика (основной текст и т.д.)
- Вложения
- затем после вложений закройте электронное письмо (это именно то, что у меня есть после моих вложений:
utl_smtp.write_data( l_conn, utl_tcp.crlf );
-- Close Email
utl_smtp.write_data( l_conn, '--' || l_boundary || '--' || utl_tcp.crlf );
utl_smtp.write_data( l_conn, utl_tcp.crlf || '.' || utl_tcp.crlf );
utl_smtp.close_data( l_conn );
utl_smtp.quit( l_conn );
Комментарии:
1. глядя на код, я не вижу различий между ним и моим кодом!!! даже у меня одинаковые значения буфера и индекса!
2. @Data-Base; добавлены некоторые комментарии, в основном убедитесь, что вложения находятся в конце электронного письма, прямо перед закрытием электронного письма.
3. теперь я вычислил это, я пропустил — принудительный повторный запуск, это может изменить l_buff_size := 57; l_idx:= 1; Спасибо, выделите
4. Любая идея, почему может привести к получению только 1 КБ из моего вложения?
Ответ №2:
У Тима Холла есть отличный сайт (oracle-base), на котором есть то, что вы ищете. Обратите особое внимание на то, как выполняется кодирование.
Я использовал аналогичный код для отправки электронных писем через pl / sql без проблем
Комментарии:
1. Согласен. Тим предоставил очень чистый код, который охватывает почти все возможности.