PL/SQL调用REST API上传附件

PL/SQL调用REST API上传附件

概述

本文主要介绍如何用PL/SQL程序调用REST API上传附件。初始代码源自github, 经过修改测试。

代码示例

sql 复制代码
  TYPE part IS RECORD(
    ds_header VARCHAR2(2048),
    ds_value  VARCHAR2(1024),
    ds_blob   BFILE);
  TYPE parts IS TABLE OF part;
v_boundary CONSTANT VARCHAR2(60) := '---------------------------30837156019033';
v_end      CONSTANT VARCHAR2(10) := '--';
  //准备http请求里包含的内容,封装在p_parts参数中
  PROCEDURE add_file
  (
    p_parts        IN OUT parts,
    p_name         IN VARCHAR2,
    p_filename     VARCHAR2,
    p_content_type VARCHAR2,
    p_blob         BFILE
  ) AS
    v_part part;
  BEGIN
   //p_name: 'file'; p_filename:文件名;v_newline: 0D0A; p_content_typ:application/pdf
    v_part.ds_header := 'Content-Disposition: form-data; name="' || p_name ||
                        '"; filename="' || p_filename || '"' || v_newline ||
                        'Content-Type: ' || p_content_type || v_newline || v_newline;
    v_part.ds_blob := p_blob;

    p_parts.extend();
    p_parts(p_parts.last) := v_part;

  END add_file;
//把parts里的内容写入http请求
  PROCEDURE send
  (
    p_req   IN OUT utl_http.req,
    p_parts IN OUT parts
  ) AS
    v_length     NUMBER := 0;
    v_length_bo  NUMBER := length(v_boundary);
    v_length_nl  NUMBER := length(v_newline);
    v_length_end NUMBER := length(v_end);

    v_step  PLS_INTEGER := 12000;
    v_count PLS_INTEGER := 0;
  BEGIN
  
    -- calculate the content-length
    v_length := v_length + v_length_end + v_length_bo + v_length_nl;
    FOR i IN p_parts.first .. p_parts.last LOOP
      v_length := v_length + length(p_parts(i).ds_header);

      IF (p_parts(i).ds_blob IS NOT NULL) THEN
        v_length := v_length + dbms_lob.getlength(p_parts(i).ds_blob);
      ELSE
        v_length := v_length + length(p_parts(i).ds_value);
      END IF;
      v_length := v_length + v_length_nl;
      v_length := v_length + v_length_end + v_length_bo;

      IF (i != p_parts.last) THEN
        v_length := v_length + v_length_nl;
      END IF;

    END LOOP;
    v_length := v_length + v_length_end + v_length_nl;

    utl_http.set_header(p_req,
                        'Content-Type',
                        'multipart/form-data; boundary=' || v_boundary);
    utl_http.set_header(p_req,
                        'Content-Length',
                        v_length);
   //用write_raw才不会有乱码,试了很多次才确定write_raw可以
    utl_http.write_raw(p_req,
                       utl_raw.cast_to_raw(v_end));
    utl_http.write_raw(p_req,
                       utl_raw.cast_to_raw(v_boundary));
    utl_http.write_raw(p_req,
                       utl_raw.cast_to_raw(v_newline));

    -- write parts
    FOR i IN p_parts.first .. p_parts.last LOOP
      utl_http.write_raw(p_req,
                         utl_raw.cast_to_raw(p_parts(i).ds_header));

      IF (p_parts(i).ds_blob IS NOT NULL) THEN

        dbms_lob.open(p_parts(i).ds_blob,
                      dbms_lob.lob_readonly);
        v_count := trunc((dbms_lob.getlength(p_parts(i).ds_blob) - 1) / v_step);
        FOR j IN 0 .. v_count LOOP
          utl_http.write_raw(p_req,
                             dbms_lob.substr(p_parts(i).ds_blob,
                                             v_step,
                                             j * v_step + 1));
        END LOOP;
        dbms_lob.close(p_parts(i).ds_blob);

      ELSE
        utl_http.write_raw(p_req,
                           utl_raw.cast_to_raw(p_parts(i).ds_value));

      END IF;

      utl_http.write_raw(p_req,
                         utl_raw.cast_to_raw(v_newline));
      utl_http.write_raw(p_req,
                         utl_raw.cast_to_raw(v_end));
      utl_http.write_raw(p_req,
                         utl_raw.cast_to_raw(v_boundary));

      IF (i != p_parts.last) THEN
        utl_http.write_raw(p_req,
                           utl_raw.cast_to_raw(v_newline));
      END IF;
    END LOOP;

    utl_http.write_raw(p_req,
                       utl_raw.cast_to_raw(v_end));
    utl_http.write_raw(p_req,
                       utl_raw.cast_to_raw(v_newline));

  END send;                     

说明

调用add_file和send两个存储过程可以准备好附件上传http请求,其余部分和调用普通REST API代码一样。

相关推荐
恒悦sunsite2 小时前
Ubuntu之apt安装ClickHouse数据库
数据库·clickhouse·ubuntu·列式存储·8123
奥尔特星云大使3 小时前
MySQL 慢查询日志slow query log
android·数据库·mysql·adb·慢日志·slow query log
来自宇宙的曹先生3 小时前
MySQL 存储引擎 API
数据库·mysql
间彧3 小时前
MySQL Performance Schema详解与实战应用
数据库
间彧3 小时前
MySQL Exporter采集的关键指标有哪些,如何解读这些指标?
数据库
weixin_446260853 小时前
Django - 让开发变得简单高效的Web框架
前端·数据库·django
mpHH4 小时前
babelfish for postgresql 分析--todo
数据库·postgresql
zizisuo4 小时前
解决在使用Lombok时maven install 找不到符号的问题
java·数据库·maven
程序边界5 小时前
国产之光!金仓数据库KingbaseES Oracle兼容性深度体验大赏
数据库·oracle
A阳俊yi5 小时前
Spring——声明式事务
java·数据库·spring