import cn.hutool.core.io.FileUtil
import cn.hutool.http.HttpResponse
import cn.hutool.http.HttpUtil
import cn.hutool.json.JSONObject
import cn.hutool.json.JSONUtil
import org.apache.commons.io.IOUtils
import org.apache.nifi.processor.io.InputStreamCallback
import java.io.ByteArrayInputStream
import java.nio.charset.StandardCharsets
/**
* 文件上传至OSS接口脚本
* 处理器:InvokeScriptedProcessor
* 创建日期:2026年08月03日
* 修改日期:2026年08月03日
* 创建人:author
* 版本:V1.0.0
* 说明:读取FlowFile内容,调用OSS上传接口,form-data方式传输文件
* 入参FlowFile属性:
* fileName: 文件基础名称
* fileType: 文件后缀类型
* token: 接口鉴权token
* url: OSS上传接口地址
* apikey: 接口密钥
*/
flowFile = session.get()
// 如果没有获取到flowFile,直接终止
if (!flowFile) {
return
}
// ========== 1、读取FlowFile属性参数 ==========
def fileName = flowFile.getAttribute("fileName")
def fileType = flowFile.getAttribute("fileType")
def accessToken = flowFile.getAttribute("token")
String url = flowFile.getAttribute("url")
String apikey = flowFile.getAttribute("apikey")
// 组装完整文件名 名称.后缀
String fullFileName = fileName + "." + fileType
// 参数非空校验,缺失参数直接路由失败
if (!fileName || !fileType || !accessToken || !url || !apikey) {
flowFile = session.putAttribute(flowFile, 'fileUpload_Error', "缺少必要参数,请检查flowFile属性")
session.transfer(flowFile, REL_FAILURE)
session.commit()
return
}
// 用来存放文件正文文本
String content = ''
// ========== 2、读取FlowFile流内容 ==========
session.read(flowFile, { inputStream ->
content = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
} as InputStreamCallback)
try {
// ========== 3、构建POST文件上传请求 ==========
HttpResponse response = HttpUtil.createPost(url)
// 显式设置请求头,multipart/form-data 文件表单上传
.header("Content-Type", "multipart/form-data")
.header("Authorization", accessToken)
.header("apikey", apikey)
// 直接传入字节流,不再落地本地磁盘,规避临时文件风险
.form("file", new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), fullFileName)
.execute()
// 获取接口返回报文
String result = response.body()
int httpCode = response.getStatus()
// 判断HTTP响应码,200区间才进行JSON解析
if (httpCode < 200 || httpCode >= 300) {
flowFile = session.putAttribute(flowFile, 'fileUpload_Error', "接口请求异常,HTTP状态码:${httpCode},返回内容:${result}")
session.transfer(flowFile, REL_FAILURE)
} else if (JSONUtil.isJson(result)) {
// 合法JSON再解析
JSONObject jsonObject = JSONUtil.parseObj(result)
String msg = jsonObject.getStr("message", "")
if ("success".equals(msg)) {
// 上传成功,解析返回data数据
JSONObject dataJson = jsonObject.getJSONObject("data")
def attrMap = [
'fileUpload_Success': result,
'fileUrl': dataJson.getStr("url"),
'fileName': dataJson.getStr("fileName"),
'originalFileName': dataJson.getStr("originalFileName"),
'fileUpload_Message': '文件上传成功'
]
flowFile = session.putAllAttributes(flowFile, attrMap)
session.transfer(flowFile, REL_SUCCESS)
} else {
// 接口返回success以外信息,业务上传失败
def attrMap = ['fileUpload_Error': result, 'fileUpload_Message': '文件上传失败']
flowFile = session.putAllAttributes(flowFile, attrMap)
session.transfer(flowFile, REL_FAILURE)
}
} else {
// 返回内容不是标准JSON
flowFile = session.putAttribute(flowFile, 'fileUpload_Error', "接口返回非JSON数据,响应内容:${result}")
session.transfer(flowFile, REL_FAILURE)
}
} catch (Exception e) {
// 捕获所有异常:网络异常、解析异常、IO异常等
def errMsg = "文件上传异常:" + e.getMessage()
flowFile = session.putAttribute(flowFile, 'fileUpload_Error', errMsg)
session.transfer(flowFile, REL_FAILURE)
}
// 提交session,完成流转
session.commit()