使用 PL/SQL HTTP 上传 BLOB 文件

Upload BLOB files using PL/SQL HTTP

通常,我使用下面的结构来发送POST请求,内容为varchar2和数字..等等

content := '{"Original File Name":"'||V_HOMEBANNER_1_EN_NAME(indx)||'"}';
  url := 'https://api.appery.io/rest/1/db/Names'; 
  req     := utl_http.begin_request(url, 'POST',' HTTP/1.1');
  UTL_HTTP.set_header(req, 'X-Appery-Database-Id', '5f2dac54b02cc6402dbe');
  utl_http.set_header(req, 'content-type', 'application/json');
  UTL_HTTP.set_header(req, 'X-Appery-Session-Token', sessionToken);
  utl_http.set_header(req, 'Content-Length', LENGTH(content));
  utl_http.write_text(req, content);
  res := utl_http.get_response(req);


BEGIN
  LOOP
    utl_http.read_line(res, buffer);
 END LOOP;
 utl_http.end_response(res);
EXCEPTION
WHEN utl_http.end_of_body THEN
  utl_http.end_response(res);
END;

而且效果很好。但是,现在我想 send/upload 一个 blob 文件(jpg 图像)变成一些 MongoDB collection 称为 'Files' (所以 url := ttps:// api.appery.io/rest/1/db/Files). collection 指南有以下 cURL 作为一般建议:

curl -X POST \
  -H "X-Appery-Database-Id: 5f2dac54b02cc6402dbe" \
  -H "X-Appery-Session-Token: <session_token>" \
  -H "Content-Type: <content_type>" \
  --data-binary '<file_content>' \
  https://api.appery.io/rest/1/db/files/<file_name>

但我无法将此 cURL 翻译成 PL/SQL 请求。具体来说,部分 (--data-binary '')

我在 Oracle table 中有这些 BLOB 文件,它们的存储名称如下:

+-----------+--------------+
| File_Name | File_content |
+-----------+--------------+
| PIC_1.jpg | BLOB         |
| PIC_2.jpg | BLOB         |
| PIC_3.jpg | BLOB         |
+-----------+--------------+

我的问题,如何将这些图片上传到目标URL?

受到@JeffreyKemp 建议的 blog 的启发,我通过仅将 write_text() 替换为 write_raw() 来工作,以便将内容正文作为 BLOB 发送(由 API).

以下代码是我的函数的关键部分,需要进行更改:

  content :=  V_HOMEBANNER_1_EN(indx);
  file_name := 'test.jpg';
  url  := 'https://api.appery.io/rest/1/db/files/'||file_name;      
  req     := utl_http.begin_request(url, 'POST',' HTTP/1.1');
  UTL_HTTP.set_header(req, 'X-Appery-Database-Id', '53fae4b02cc4021dbe');
  UTL_HTTP.set_header(req, 'X-Appery-Session-Token', sessionToken);
  utl_http.set_header(req, 'content-type', 'image/jpeg');
  req_length := DBMS_LOB.getlength(CONTENT);
  DBMS_OUTPUT.PUT_LINE(req_length);


  --IF MSG DATA UNDER 32KB LIMIT:
  IF req_length <= 32767
  THEN 
  begin
  utl_http.set_header(req, 'Content-Length', req_length);
  utl_http.write_raw(req, content);
  exception
  when others then
  DBMS_OUTPUT.PUT_LINE(sqlerrm);
  end;

  --IF MSG DATA MORE THAN 32KB
  ELSIF req_length >32767
  THEN
  BEGIN
  DBMS_OUTPUT.PUT_LINE(req_length);
  utl_http.set_header(req, 'Transfer-Encoding', 'Chunked');
  WHILE (offset < req_length)
  LOOP
  DBMS_LOB.read(content, amount, offset, buffer);
  utl_http.write_raw(req, buffer);
  offset := offset + amount;
  END LOOP;
  exception
  when others then
  DBMS_OUTPUT.PUT_LINE(sqlerrm);
  end;


  END IF;

  l_http_response := UTL_HTTP.get_response(req);
  UTL_HTTP.read_text(l_http_response, response_body, 32767);
  UTL_HTTP.end_response(l_http_response);

尝试和测试大于和小于 32KB images/jpg。