Oracle

게시글 보기
작성자 유건데이타 등록일 2015-05-16
제목 BLOB 컬럼에 들어있는 이미지를 보는 cgi 프로그램
BLOB 컬럼에 들어있는 이미지를 WEB BROWSER 를 통해서 보는 방법
으로는 PL/SQL Cartridge를 이용할 수도 있고 PRO*C로 CGI 프로그램
을 만들어서 처리하는 방법이 있다.

그런데, PL/SQL Cartridge를 이용하는 방법은 Database Characterset
이 WE8ISO8859P1인 경우에만 가능하기 때문에 일반적으로 많이 사용되는
KO16KSC5601 환경에서는 이미지가 제대로 출력되지 않는다.

따라서, 대부분의 경우에는 PRO*C로 CGI 프로그램을 만들어야 하는데,
LONG RAW 컬럼에 들어있는 이미지를 보여주는 경우와 접근방법은 같지만
몇가지 차이점이 있다.

아래의 예제에서는 IMAGETABE 테이블의 IMAGE 컬럼에 들어있는 이미지
를 보여주는 경우를 보여주고 있다.

LONG RAW 컬럼의 경우와 비교해서 다른 점은 다음과 같다.

1. MIME TYPE 을 출력할 때 printf 대신에 write 를 사용해야 한다.
정확한 이유는 알 수 없지만 printf 를 사용하게 되면 Document Contains
No Data 에러가 발생하는 경우가 있다.

2. LONG RAW 컬럼의 경우에는 이미지를 한번에 변수로 받아 와야 하기 때문에
이미지 크기 만큼 메모리를 할당받아서 처리해야 한다. 그런데, BLOB 의
경우에는 작은 크기만큼 여러번 나누어서 가져올 수 있기 때문에 적은 메
모리만 할당 받아서 처리할 수 있다. 처리 단위를(아래에서는 4096 바이트)
키우면 속도는 증가되지만 메모리를 많이 필요로 하게 된다.
최대 값은 32K 까지 가능하다.


<<< 테이블 구조 >>>


CREATE TABLE IMAGETAB
(NO NUMBER,
IMAGE BLOB);



<<< BLOB 처리하는 PACKAGE >>>


create or replace package blob_it as
my_blob blob;

function get_blob_len return number;

procedure read_blob(amount in out number, offset in number,
buf in out raw);
end;
/

create or replace package body blob_it as
function get_blob_len return number is
begin
return DBMS_LOB.GETLENGTH(my_blob);
end;

procedure read_blob(amount in out number, offset in number,
buf in out raw) is
begin
DBMS_LOB.READ(my_blob,amount,offset,buf);
end;
end;
/


<<< BLOB 컬럼의 이미지를 보여주는 CGI 프로그램 >>>


#include
#include

#define MAXSIZE 4096

EXEC SQL INCLUDE SQLCA;

typedef struct
{
short len;
char buf[MAXSIZE];
} long_varraw;

EXEC SQL TYPE long_varraw IS VARRAW(MAXSIZE);
long_varraw lvr;

main()
{
long amount;
long offset;
short done;
long total;
char *mimetype="Content-Type: image/jpeg\n\n";
char *userid="park/park";


EXEC SQL WHENEVER SQLERROR DO sql_error();

EXEC SQL CONNECT :userid;

EXEC SQL EXECUTE
BEGIN
select image into blob_it.my_blob from imagetab
where no = 1;
:total := DBMS_LOB.GETLENGTH(blob_it.my_blob);
END;
END-EXEC;

amount = MAXSIZE;
offset = 1;
done = 0;

write(1, mimetype, strlen(mimetype));

while (!done)
{
EXEC SQL EXECUTE
BEGIN
DBMS_LOB.READ(blob_it.my_blob,:amount,:offset,:lvr);
END;
END-EXEC;

offset += amount;

if (offset >= total)
done = 1;

write(1,(void *)lvr.buf,(size_t)amount);
}

EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL ROLLBACK WORK RELEASE;
}


int sql_error()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;

printf("%s\n",sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
exit(1);
}
Comment
등록된 코멘트가 없습니다.