暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle FOPEN到子文件夹

askTom 2018-08-22
767

问题描述

您好,我正在尝试找到一种将文件写入Oracle目录的子文件夹的方法。我可以写入oracle目录的基础,但不能写入子文件夹。

为了保持简单,这就是我们目前的工作原理,之后是我们需要的。

  V_BLOB_LENGTH         := DBMS_LOB.GETLENGTH (V_BLOB);
  V_OUT_FILE            := UTL_FILE.FOPEN (P_ORA_DIR, P_FILE_NAME, 'wb', V_CHUNK_SIZE);
   
  WHILE V_BLOB_POSITION <= V_BLOB_LENGTH
  LOOP
    IF V_BLOB_POSITION                                    + V_CHUNK_SIZE - 1 > V_BLOB_LENGTH THEN
      V_CHUNK_SIZE                       := V_BLOB_LENGTH - V_BLOB_POSITION + 1;
    END IF;
    DBMS_LOB.READ (V_BLOB, V_CHUNK_SIZE, V_BLOB_POSITION, V_BUFFER);
    UTL_FILE.PUT_RAW (V_OUT_FILE, V_BUFFER, TRUE);
    V_BLOB_POSITION := V_BLOB_POSITION + V_CHUNK_SIZE;
  END LOOP;
  UTL_FILE.FCLOSE (V_OUT_FILE);


唯一的区别是将 '/子文件夹/' 添加到FOPEN中的文件名

  V_BLOB_LENGTH         := DBMS_LOB.GETLENGTH (V_BLOB);
  V_OUT_FILE            := UTL_FILE.FOPEN (P_ORA_DIR, '/subfolder/'||P_FILE_NAME, 'wb', V_CHUNK_SIZE);
   
  WHILE V_BLOB_POSITION <= V_BLOB_LENGTH
  LOOP
    IF V_BLOB_POSITION                                    + V_CHUNK_SIZE - 1 > V_BLOB_LENGTH THEN
      V_CHUNK_SIZE                       := V_BLOB_LENGTH - V_BLOB_POSITION + 1;
    END IF;
    DBMS_LOB.READ (V_BLOB, V_CHUNK_SIZE, V_BLOB_POSITION, V_BUFFER);
    UTL_FILE.PUT_RAW (V_OUT_FILE, V_BUFFER, TRUE);
    V_BLOB_POSITION := V_BLOB_POSITION + V_CHUNK_SIZE;
  END LOOP;
  UTL_FILE.FCLOSE (V_OUT_FILE);


原因: 我们有动态项目,每个项目包含大约5000个,每个子文件夹2个文件。我们可以在使用BFILE放置在子文件夹中时读取文件,但是我们需要创建一个html上传系统而不是FTP帐户。

所以基本上,他们是使以下工作的一种方式:
UTL_FILE.FOPEN (P_ORA_DIR, '/subfolder/'||P_FILE_NAME, 'wb', V_CHUNK_SIZE)


当前,当我们将文件夹名称附加到文件时,它只是忽略它并将其放置在Oracle目录的根目录中。任何建议将不胜感激。

专家解答

这是安全限制。因为否则,为 (例如) “/u01” 创建的Oracle directory对象可能具有对其下方所有文件夹的读/写访问权限,这可能是灾难性的。

如果需要,您可以使用包装器动态处理此问题,以创建目录,例如

SQL> grant create any directory to mcdonac;

Grant succeeded.

SQL> create or replace directory TEMP as 'c:\temp';

Directory created.

SQL>
SQL> create or replace
  2  procedure my_fopen(fname varchar2) is
  3    subdir varchar2(100);
  4    filename varchar2(100);
  5    dirhash number;
  6    direxists int;
  7  begin
  8    if fname like '%\%' then
  9      subdir := substr(fname,1,instr(fname,'\',-1,1));
 10      filename := substr(fname,1+instr(fname,'\',-1,1));
 11      dbms_output.put_line('Directory = '||subdir);
 12      dbms_output.put_line('Filename = '||filename);
 13
 14      select ora_hash(subdir) into dirhash from dual;
 15      select count(*)
 16      into   direxists
 17      from   all_directories
 18      where  directory_name = 'TEMP_'||dirhash;
 19
 20      if direxists = 1 then
 21        dbms_output.put_line('Directory already exists as '||'TEMP_'||dirhash);
 22      else
 23        dbms_output.put_line('Creating new directory '||'TEMP_'||dirhash);
 24        dbms_output.put_line('create directory '||'TEMP_'||dirhash||' as ''c:\temp\'||subdir||'''');
 25        execute immediate 'create directory '||'TEMP_'||dirhash||' as ''c:\temp\'||subdir||'''';
 26      end if;
 27    else
 28      dbms_output.put_line('Directory = TEMP');
 29      dbms_output.put_line('Filename = '||fname);
 30    end if;
 31  end;
 32  /

Procedure created.

SQL> sho err
No errors.
SQL>
SQL> set serverout on
SQL> exec my_fopen('abc.dat');
Directory = TEMP
Filename = abc.dat

PL/SQL procedure successfully completed.

SQL> exec my_fopen('subdir\abc.dat');
Directory = subdir\
Filename = abc.dat
Creating new directory TEMP_3814585973
create directory TEMP_3814585973 as 'c:\temp\subdir\'

PL/SQL procedure successfully completed.

SQL> exec my_fopen('subdir\abc.dat');
Directory = subdir\
Filename = abc.dat
Directory already exists as TEMP_3814585973

PL/SQL procedure successfully completed.

SQL>
SQL>
SQL>
SQL>


因此,当您第一次打开文件时,您正在根据需要为任何必需的子文件夹创建一个目录。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论