【问题标题】:Generate the URL of a Remote File using PL/SQL使用 PL/SQL 生成远程文件的 URL
【发布时间】:2017-01-11 03:35:06
【问题描述】:

created a Concurrent Program 使用 PL/SQL 从一个长的参数化查询创建一个 Excel 文件。 程序成功完成后,该文件将放置在远程服务器的目录中,通常大小约为 4 MB。 我正在考虑一种通知请求者并使他/她能够将文件保存到其本地目录的方法。 但是,由于 32 KB 的限制,我无法使用 UTL_MAIL 附加并通过电子邮件发送文件。 (Does UTL_MAIL have an attachment limit of 32k)。

在同一篇文章中,Tom Kyte 首选的方法是:

  1. 将附件存储到数据库中。
  2. 通过电子邮件发送带有链接的非常小的电子邮件。链接指向我的数据库 - 使用 URL。

因此,我正在考虑采用相同的方法并使用下面的块通知请求者并使他/她能够下载所述 Excel 文件:

declare

    l_url_link  varchar2(100);  -- how can i get the URL of the File?

BEGIN 

    UTL_MAIL.SEND(sender     => 'xxx@oracle.com'
                , recipients => 'Migs.Isip.23@Gmail.com'
                , subject    => 'Testmail'
                , message    => 'Your File is Ready to be downloaded, click the link here: '||l_url_link);

END;

我的问题是:

  1. 如何使用 PL/SQL 生成远程文件的“URL”?
  2. 是否需要授予用户访问远程服务器的权限才能下载文件?

谢谢!

Oracle 数据库版本:

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
"CORE   11.2.0.4.0  Production"
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

【问题讨论】:

  • Did you see the follow-up? 如果您将文件写入文件系统目录而不是将其存储在数据库中(作为 CLOB/BLOB?),您可以使用 FTP 服务器或 Web 服务器,或者中间件...我们对您现有的基础架构、您可以添加的内容或可以公开的内容一无所知。
  • 嗨@AlexPoole,是的,我看到了,但我不太明白。感谢您的澄清。我正在将文件写入应用程序服务器。如果文件来自应用服务器,你能建议一种方法吗?谢谢!
  • 我有一个答案,但希望您确认您的并发程序是如何运行的 - 您正在运行电子商务套件吗?
  • 嗨@PeteMahon,是的,EBS 12.1.3,我目前正在尝试将其插入FND_LOBS,然后使用FND_GFM 包生成一个URL。请让我知道您对此的建议。谢谢!

标签: oracle plsql


【解决方案1】:

这是我编写的一个 pl/sql 函数,用于检索并发日志文件或输出文件的 URL。如果您将 Excel 文件写入并发输出,这应该可以正常工作。让我知道你是怎么办的。我没有检查这是否会给出正确的 mime 类型或扩展名 - 不确定 EBS 如何处理这个问题,但函数本身肯定会按 12.1.3 的原样编译。

规格

FUNCTION  get_concurrent_url (p_file_type   IN  VARCHAR2
                             ,p_request_id  IN  NUMBER
                             ,p_expiry      IN  NUMBER)
RETURN VARCHAR2;

身体

/*  Get a URL to view the log/output
    File Type is LOG or OUT 
    Request ID is the concurrent request ID
    Expiry is in minutes                                                */
FUNCTION  get_concurrent_url (p_file_type   IN  VARCHAR2
                             ,p_request_id  IN  NUMBER
                             ,p_expiry      IN  NUMBER)
RETURN VARCHAR2                             
IS 

CURSOR c_gwyuid
IS
    SELECT  profile_option_value
    FROM    fnd_profile_options         FPO
           ,fnd_profile_option_values   FPOV
    WHERE   FPO.profile_option_name     =   'GWYUID'
    AND     FPO.application_id          =   FPOV.application_id
    AND     FPO.profile_option_id       =   FPOV.profile_option_id; 

CURSOR c_two_task     
IS
    SELECT  profile_option_value
    FROM    fnd_profile_options         FPO
           ,fnd_profile_option_values   FPOV
    WHERE   FPO.profile_option_name     =   'TWO_TASK'
    AND     FPO.application_id          =   FPOV.application_id
    AND     FPO.profile_option_id       =   FPOV.profile_option_id;

l_request_id        NUMBER;
l_file_type         VARCHAR2 (3 BYTE);
l_expiry            NUMBER;
l_two_task          VARCHAR2 (100 BYTE);
l_gwyuid            VARCHAR2 (100 BYTE);
l_url               VARCHAR2 (1024 BYTE); 

BEGIN

l_request_id    :=  p_request_id;
l_file_type     :=  p_file_type;
l_expiry        :=  p_expiry;

FOR i IN c_gwyuid LOOP
    l_gwyuid := i.profile_option_value;
END LOOP;

FOR i IN c_two_task LOOP
    l_two_task := i.profile_option_value;
END LOOP;        

IF l_file_type = 'LOG' THEN  
    l_url := fnd_webfile.get_url
                (file_type      =>  fnd_webfile.request_log
                ,id             =>  l_request_id
                ,gwyuid         =>  l_gwyuid
                ,two_task       =>  l_two_task
                ,expire_time    =>  l_expiry);
ELSE 
    l_url := fnd_webfile.get_url
                (file_type      =>  fnd_webfile.request_out
                ,id             =>  l_request_id
                ,gwyuid         =>  l_gwyuid
                ,two_task       =>  l_two_task
                ,expire_time    =>  l_expiry);
END IF;

RETURN l_url;

END get_concurrent_url;

【讨论】:

  • 不幸的是,该文件没有被写入输出。它作为二进制xlsx 文件写入操作系统。但我会随身携带。谢谢!
【解决方案2】:

我能够使用 Oracle EBS 中的 FND_GFM 文件上传程序包(略有不同)找到解决方案。 FND_GFM是Oracle EBS前端应用页面上传文件时常用的包。

首先,使用上一篇文章中的代码生成 Excel 文件 (xlsx):Create an Excel File (.xlsx) using PL/SQL

然后将文件插入FND_LOBS 并从操作系统中删除(为了良好的内务管理),最后使用UTL_FILE 作为电子邮件发送:

procedure generate_and_send_excel
is

    l_content   varchar2(250);
    l_file_url  varchar2(4000);  
    l_directory varchar2(250);
    l_filename  varchar2(250);
    l_message   clob;
    l_instance   varchar2(100);
    l_ebs_url    varchar2(100);

begin

    /* your excel generation code here */

    l_content   := 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    l_directory := 'EXT_TAB_DATA';
    l_filename  := 'report.xlsx';

    select  instance_name
    into    l_instance
    from    v$instance;

    select  home_url
    into    l_ebs_url
    from    icx_parameters;

    IMPORT_TO_LOB (p_file_name    => l_filename          -- this is the actual filename of the saved OS File
                 , p_directory    => l_directory         -- should be a defined directory in the Database
                 , p_content_type => l_content           -- standard for Excel Files
                 , p_program_name => 'your prog here'
                 , p_program_tag  => 'your prog here'
                 , p_file_url     => l_file_url);        -- this will be the generated URL of your File

    utl_file.fremove(l_directory, l_filename);

    l_message := l_message||'<h2 style="color: #5e9ca0;">'||l_title||'</h2>';
    l_message := l_message||'<h3 style="color: #2e6c80;">Report is Ready for Download: <a href="'||l_file_url||'">'||l_filename||'</a></h3>';
    l_message := l_message||'<p>File was generated on '|| sysdate ||' from <a href="'||l_ebs_url||'">'||l_instance||'</a></p>';
    l_message := l_message||'<strong>Regards,</strong><br/><strong>Sample Team</strong>';
    l_message := l_message||'<br/><a href="mailto:ERPSupport@alorica.com">Sample@sample.com</a>';


    UTL_MAIL.SEND(sender     => 'SAMPLE@SAMPLE.com'
                , recipients => 'Migs.Isip.23@gmail.com'
                , subject    => 'Hello message'
                , message    => l_message
                , mime_type  => 'text/html; charset=us-ascii');

end generate_and_send_excel;

插入FND_LOBS 的步骤如下(没有可用的种子 API):

Procedure IMPORT_TO_LOB (p_file_name    IN  FND_LOBS.FILE_NAME%TYPE
                       , p_directory    IN  dba_directories.directory_name%type  
                       , p_content_type IN  FND_LOBS.file_content_type%type
                       , p_program_name IN  FND_LOBS.program_name%type
                       , p_program_tag  IN  FND_LOBS.program_tag%type
                       , p_language     IN  FND_LOBS.language%type      default 'US'
                       , p_file_format  IN  FND_LOBS.file_format%type   default 'binary'
                       , p_file_url     OUT varchar2)
IS
    PRAGMA AUTONOMOUS_TRANSACTION;
    lBlob               BLOB;
    lFile               BFILE := BFILENAME(p_directory, p_file_name);
    L_ORA_CHARSET       VARCHAR2(100);
    P_COUNT             NUMBER;

BEGIN

    SELECT  value 
    into    l_ora_charset
    FROM    nls_database_parameters
    where   parameter = 'NLS_CHARACTERSET';

    insert into FND_LOBS 
    (
        file_id
    ,   file_name
    ,   file_content_type
    ,   file_data
    ,   upload_date
    ,   expiration_date
    ,   program_name
    ,   program_tag
    ,   LANGUAGE
    ,   oracle_charset
    ,   file_format
    )
    values
    (
        fnd_lobs_s.NEXTVAL        -- FILE_ID
    ,   p_file_name               -- FILE_NAME
    ,   p_content_type            -- FILE_CONTENT_TYPE
    ,   EMPTY_BLOB()              -- FILE_DATA
    ,   sysdate                   -- UPLOAD_DATE
    ,   NULL                      -- EXPIRATION_DATE
    ,   p_program_name            -- PROGRAM_NAME
    ,   p_program_tag             -- PROGRAM_TAG
    ,   p_language                -- LANGUAGE
    ,   l_ora_charset             -- ORACLE_CHARSET
    ,   p_file_format             -- FILE_FORMAT   
    )
    RETURNING file_data INTO lBlob;

    DBMS_LOB.OPEN(lFile, DBMS_LOB.LOB_READONLY);
    DBMS_LOB.OPEN(lBlob, DBMS_LOB.LOB_READWRITE);
    DBMS_LOB.LOADFROMFILE(DEST_LOB => lBlob,
                          SRC_LOB  => lFile,
                          AMOUNT   => DBMS_LOB.GETLENGTH(lFile));                              
    DBMS_LOB.CLOSE(lFile);
    DBMS_LOB.CLOSE(lBlob);        

    commit;

    p_file_url := fnd_gfm.construct_download_url (fnd_web_config.gfm_agent, fnd_lobs_s.currval);

END IMPORT_TO_LOB;

请注意,这是一个AUTONOMOUS_TRANSACTION,因此需要在返回调用包/块之前提交它。

希望有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    相关资源
    最近更新 更多