Skip to content

Instantly share code, notes, and snippets.

@seraphy
Created December 27, 2011 09:51
Show Gist options
  • Select an option

  • Save seraphy/1523176 to your computer and use it in GitHub Desktop.

Select an option

Save seraphy/1523176 to your computer and use it in GitHub Desktop.
PL/SQLでメールの添付ファイルのファイル名のエンコードをRFC2231により行う
declare
-- UTF8のOracle表現
UTF8 constant nvarchar2(250) := 'AL32UTF8';
-- 改行コード
CRLF CONSTANT VARCHAR2(2) := chr(13) || chr(10);
-- タブコード
TAB CONSTANT VARCHAR2(1) := chr(9);
/**
* 添付ファイルのファイル名のエンコードをRFC2231により行う.
* 「filename*N*=xxxx」の形式の複数行となり、継続する場合は末尾はセミコロンとなる。
* エンコードは文字コード名の識別子につづいて16進数でエンコードされた文字が続く.
* (例) filename*0*=UTF-8''%E6%96%B0%E8%A6
* http://www.asahi-net.or.jp/~BD9Y-KTU/htmlrel_f/dtd_f/rfc_f/rfc2231j.html
* http://adiary.blog.abk.nu/0253
* @param filename 添付ファイル名
* @return UTF8の16進数表現でエンコードされたファイル名表現
*/
FUNCTION MAKE_ATTACHED_FILE_NAME(filename NVARCHAR2) RETURN RAW AS
buf RAW(32760);
c RAW(1);
pos PLS_INTEGER := 1;
mxlen PLS_INTEGER;
linebuf VARCHAR2(80) := 'UTF-8''''';
TYPE t_lines IS TABLE OF VARCHAR2(80) INDEX BY binary_integer;
lines t_lines;
BEGIN
IF filename IS NULL THEN
RETURN NULL;
END IF;
-- ファイル名をUTF8のバイナリに変換
buf := UTL_I18N.STRING_TO_RAW(filename, UTF8);
-- バイナリから「16進数」の文字列に変換。
-- 54文字を超えた場合は次の行に折り返す.
mxlen := UTL_RAW.LENGTH(buf);
LOOP
EXIT WHEN pos > mxlen;
IF LENGTH(linebuf) > 54 THEN
lines(lines.COUNT) := linebuf || ';';
linebuf := NULL;
END IF;
c := utl_raw.substr(buf, pos, 1);
linebuf := linebuf || '%' || rawtohex(c);
pos := pos + 1;
END LOOP;
lines(lines.COUNT) := linebuf;
-- ヘッダを構築してバイナリとして構築する.
buf := NULL;
FOR idx IN lines.FIRST .. lines.LAST
LOOP
IF lines.COUNT > 1 THEN
linebuf := TAB || 'filename*' || idx || '*=' || lines(idx);
ELSE
linebuf := TAB || 'filename*=' || lines(0);
END IF;
buf := UTL_RAW.CONCAT(
buf,
UTL_RAW.CAST_TO_RAW(linebuf),
UTL_RAW.CAST_TO_RAW(CRLF)
);
END LOOP;
RETURN buf;
END;
begin
declare
mes nvarchar2(80) := '新規テキスト ドキュメント~森鷗外.txt';
begin
dbms_output.put_line(
UTL_RAW.CAST_TO_VARCHAR2(
MAKE_ATTACHED_FILE_NAME(mes)
)
);
end;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment