如何将BLOB映像复制到文件系统

时间:2017-12-27 12:00:02

标签: sql oracle11g oracle-apex

我在这里被告知

https://softwareengineering.stackexchange.com/questions/362992/all-images-on-a-single-table-is-a-good-idea/363007#363007

将图像存储在文件系统中,而不是在表格中存储BLOB。

如何将BLOB复制到文件中,并获取其路径(由APEX应用程序访问)?

我想创建一个将BLOB映像保存到文件系统的触发器,并将路径保存到varchar列。

该表具有类似

的结构
CREATE TABLE "ALLIMAGES_TBL" 
   (    "ID" NUMBER NOT NULL ENABLE, 
        "NAME" NVARCHAR2(400), 
        "FILENAME" VARCHAR2(350 BYTE), 
        "MIME_TYPE" VARCHAR2(255 BYTE), 
        "SIZE" NUMBER, 
        "CHARSET" VARCHAR2(128 BYTE), 
        "LAST_UPDATE_DATE" DATE, 
        "BinaryBLOB" BLOB, 
        "PATH" varchar(260), 

1 个答案:

答案 0 :(得分:0)

与往常一样,这两个选项都有 pro contra :将图像保存在数据库中,或将它们保存在文件系统中。在我看来,如果只有少数(好的,让我们在大约100秒内测量它们),我宁愿把它们放在一张桌子里。处理它们更容易。因为,一旦他们在文件系统中,你将不得不取得&使用更多(HTML)代码在Apex中显示它们。

无论如何,这是我如何做到的(在以前的Apex版本之一,我相信它是4.0):使用“文件浏览”项目我暂时将图像存储到一个表中(它是WWW_FLOW_FILES;你宁愿使用你的现在拥有自己的表),然后 - 按下按钮触发进程 - 我将它们移动到一个目录中。

流程代码:

declare
  -- l_dest_dir is name of the directory (Oracle object) which points
  -- to a filesystem directory
  l_dest_dir varchar2(30) := pkg_slike.f_dir_slike_upload_dp(:P0_DP);
begin
  for cur_r in (select id, filename 
                from wwv_flow_files
                where upper(filename) like 'TS%.JP%G' 
               )
  loop
    -- put a picture into L_DEST_DIR
    pkg_slike.p_write_blob_to_file(cur_r.id, l_dest_dir);

    delete from wwv_flow_files
      where id = cur_r.id;
  end loop;
end;

程序代码:

   PROCEDURE p_write_blob_to_file (p_file_id IN NUMBER, p_dir IN VARCHAR2)
   IS
      /* 19.04.2012. Taken from Eddie Awad's Blog
                     http://awads.net/wp/2011/09/20/create-an-application-to-upload-files-using-oracle-apex-in-less-than-10-minutes-video/
      */
      l_blob            BLOB;
      l_blob_length     INTEGER;
      l_out_file        UTL_FILE.file_type;
      l_buffer          RAW (32767);
      l_chunk_size      BINARY_INTEGER := 32767;
      l_blob_position   INTEGER := 1;
      l_file_name       pkg_general.subt_ime_slike;
   BEGIN
      -- Retrieve the BLOB for reading
      SELECT blob_content, filename
        INTO l_blob, l_file_name
        FROM wwv_flow_files
       WHERE id = p_file_id;

      -- Retrieve the SIZE of the BLOB
      l_blob_length := DBMS_LOB.getlength (l_blob);

      -- Open a handle to the location where you are going to write the BLOB
      -- to file.
      -- NOTE: The 'wb' parameter means "write in byte mode" and is only
      --       available in the UTL_FILE package with Oracle 10g or later
      l_out_file :=
         UTL_FILE.fopen (p_dir,
                         l_file_name,
                         'wb' -- important. If ony w then extra carriage return/line brake
                             ,
                         l_chunk_size);

      -- Write the BLOB to file in chunks
      WHILE l_blob_position <= l_blob_length
      LOOP
         IF l_blob_position + l_chunk_size - 1 > l_blob_length
         THEN
            l_chunk_size := l_blob_length - l_blob_position + 1;
         END IF;

         DBMS_LOB.read (l_blob,
                        l_chunk_size,
                        l_blob_position,
                        l_buffer);
         UTL_FILE.put_raw (l_out_file, l_buffer, TRUE);
         l_blob_position := l_blob_position + l_chunk_size;
      END LOOP;

      -- Close the file handle
      UTL_FILE.fclose (l_out_file);
   END p_write_blob_to_file;

希望您能够根据自己的情况调整它。