|
|
|
package com.zhonglai.luhui.api.util.jimeng;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
|
import com.ruoyi.common.utils.file.FileUtils;
|
|
|
|
|
|
|
|
import javax.crypto.Mac;
|
|
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
|
import java.io.*;
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
import java.nio.charset.Charset;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
import java.security.MessageDigest;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copyright (year) Beijing Volcano Engine Technology Ltd.
|
|
|
|
* <p>
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
* <p>
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
* <p>
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class Sign {
|
|
|
|
|
|
|
|
private static final BitSet URLENCODER = new BitSet(256);
|
|
|
|
|
|
|
|
private static final String CONST_ENCODE = "0123456789ABCDEF";
|
|
|
|
public static final Charset UTF_8 = StandardCharsets.UTF_8;
|
|
|
|
|
|
|
|
private final String region;
|
|
|
|
private final String service;
|
|
|
|
private final String schema;
|
|
|
|
private final String host;
|
|
|
|
private final String path;
|
|
|
|
private final String ak;
|
|
|
|
private final String sk;
|
|
|
|
|
|
|
|
static {
|
|
|
|
int i;
|
|
|
|
for (i = 97; i <= 122; ++i) {
|
|
|
|
URLENCODER.set(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 65; i <= 90; ++i) {
|
|
|
|
URLENCODER.set(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 48; i <= 57; ++i) {
|
|
|
|
URLENCODER.set(i);
|
|
|
|
}
|
|
|
|
URLENCODER.set('-');
|
|
|
|
URLENCODER.set('_');
|
|
|
|
URLENCODER.set('.');
|
|
|
|
URLENCODER.set('~');
|
|
|
|
}
|
|
|
|
|
|
|
|
public Sign(String region, String service, String schema, String host, String path, String ak, String sk) {
|
|
|
|
this.region = region;
|
|
|
|
this.service = service;
|
|
|
|
this.host = host;
|
|
|
|
this.schema = schema;
|
|
|
|
this.path = path;
|
|
|
|
this.ak = ak;
|
|
|
|
this.sk = sk;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
String SecretAccessKey = "TTJKbU1tSXdOV1V3Tnprd05HUXhZamsxTWpVNVlXUm1OVGxoWlRjeE9UQQ==";
|
|
|
|
String AccessKeyID = "AKLTYTQ5ODYxYjU5NjNjNGJhZGJhNTZlYjk2MWIwZjJlMDc";
|
|
|
|
iamApi(SecretAccessKey,AccessKeyID);
|
|
|
|
String str = CVSync2AsyncSubmitTaskApi(SecretAccessKey,AccessKeyID,"a cat",true,-1,512,512);
|
|
|
|
JSONObject jsonObject = JSONObject.parseObject(str);
|
|
|
|
if(jsonObject.containsKey("code") && jsonObject.getInteger("code")==10000)
|
|
|
|
{
|
|
|
|
JSONObject data = jsonObject.getJSONObject("data");
|
|
|
|
if(data.containsKey("task_id") && data.getString("task_id").length()>0)
|
|
|
|
{
|
|
|
|
String task_id = data.getString("task_id");
|
|
|
|
String imgstr = CVSync2AsyncGetResultApi(SecretAccessKey,AccessKeyID,task_id);
|
|
|
|
jsonObject = JSONObject.parseObject(imgstr);
|
|
|
|
data = jsonObject.getJSONObject("data");
|
|
|
|
if(jsonObject.containsKey("code") && jsonObject.getInteger("code")==10000)
|
|
|
|
{
|
|
|
|
while (data.containsKey("status") && data.getString("status").equals("in_queue"))
|
|
|
|
{
|
|
|
|
Thread.sleep(5000);
|
|
|
|
imgstr = CVSync2AsyncGetResultApi(SecretAccessKey,AccessKeyID,task_id);
|
|
|
|
jsonObject = JSONObject.parseObject(imgstr);
|
|
|
|
data = jsonObject.getJSONObject("data");
|
|
|
|
}
|
|
|
|
imgstr = CVSync2AsyncGetResultApi(SecretAccessKey,AccessKeyID,task_id);
|
|
|
|
jsonObject = JSONObject.parseObject(imgstr);
|
|
|
|
data = jsonObject.getJSONObject("data");
|
|
|
|
JSONArray img_bt = data.getJSONArray("binary_data_base64");
|
|
|
|
List<String> base64List = img_bt.toJavaList(String.class);
|
|
|
|
saveImageFromBase64Array(base64List, "uploadPath/upload/test/" + task_id + ".jpg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* 将 Base64 字符串数组保存为图片
|
|
|
|
*
|
|
|
|
* @param base64Array Base64 字符串数组
|
|
|
|
* @param outputPath 输出图片路径
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
|
|
|
public static void saveImageFromBase64Array(List<String> base64Array, String outputPath) throws IOException {
|
|
|
|
// 1. 拼接所有 Base64 字符串
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
for (String part : base64Array) {
|
|
|
|
sb.append(part);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2. 解码 Base64
|
|
|
|
byte[] imageBytes = Base64.getDecoder().decode(sb.toString());
|
|
|
|
|
|
|
|
File parentFile = new File(outputPath).getParentFile();
|
|
|
|
if (!parentFile.exists())
|
|
|
|
{
|
|
|
|
parentFile.mkdirs();
|
|
|
|
}
|
|
|
|
// 3. 写入文件
|
|
|
|
try (FileOutputStream fos = new FileOutputStream(outputPath)) {
|
|
|
|
fos.write(imageBytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
System.out.println("图片保存成功: " + outputPath);
|
|
|
|
}
|
|
|
|
public static String CVSync2AsyncGetResultApi(String SecretAccessKey,String AccessKeyID,String task_id ) throws Exception {
|
|
|
|
// 请求地址
|
|
|
|
String endpoint = "visual.volcengineapi.com";
|
|
|
|
String path = "/"; // 路径,不包含 Query// 请求接口信息
|
|
|
|
String service = "cv";
|
|
|
|
String region = "cn-north-1";
|
|
|
|
String schema = "https";
|
|
|
|
Sign sign = new Sign(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
|
|
|
|
|
|
|
|
String action = "CVSync2AsyncGetResult";
|
|
|
|
String version = "2022-08-31";
|
|
|
|
|
|
|
|
Date date = new Date();
|
|
|
|
JSONObject bodyJson = new JSONObject();
|
|
|
|
bodyJson.put("req_key", "jimeng_t2i_v31");
|
|
|
|
bodyJson.put("task_id", task_id);
|
|
|
|
JSONObject req_json = new JSONObject();
|
|
|
|
req_json.put("return_url", true);
|
|
|
|
bodyJson.put("req_json", req_json);
|
|
|
|
HashMap<String, String> queryMap = new HashMap() {{
|
|
|
|
}};
|
|
|
|
String contentType = "application/json";
|
|
|
|
return sign.doRequest("POST", queryMap, bodyJson.toJSONString().getBytes(Charset.forName("UTF-8")), date, action, version,contentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String CVSync2AsyncSubmitTaskApi(String SecretAccessKey,String AccessKeyID,String prompt,Boolean use_pre_llm,Integer seed,Integer width,Integer height) throws Exception {
|
|
|
|
// 请求地址
|
|
|
|
String endpoint = "visual.volcengineapi.com";
|
|
|
|
String path = "/"; // 路径,不包含 Query// 请求接口信息
|
|
|
|
String service = "cv";
|
|
|
|
String region = "cn-north-1";
|
|
|
|
String schema = "https";
|
|
|
|
Sign sign = new Sign(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
|
|
|
|
|
|
|
|
String action = "CVSync2AsyncSubmitTask";
|
|
|
|
String version = "2022-08-31";
|
|
|
|
|
|
|
|
Date date = new Date();
|
|
|
|
JSONObject bodyJson = new JSONObject();
|
|
|
|
bodyJson.put("req_key", "jimeng_t2i_v31");
|
|
|
|
bodyJson.put("prompt", prompt);
|
|
|
|
if (null != use_pre_llm)
|
|
|
|
{
|
|
|
|
bodyJson.put("use_pre_llm", use_pre_llm);
|
|
|
|
}
|
|
|
|
if (null != seed)
|
|
|
|
{
|
|
|
|
bodyJson.put("seed", seed);
|
|
|
|
}
|
|
|
|
if (width != null)
|
|
|
|
{
|
|
|
|
bodyJson.put("width", width);
|
|
|
|
}
|
|
|
|
if (height != null)
|
|
|
|
{
|
|
|
|
bodyJson.put("height", height);
|
|
|
|
}
|
|
|
|
HashMap<String, String> queryMap = new HashMap() {{
|
|
|
|
}};
|
|
|
|
String contentType = "application/json";
|
|
|
|
return sign.doRequest("POST", queryMap, bodyJson.toJSONString().getBytes(Charset.forName("UTF-8")), date, action, version,contentType);
|
|
|
|
}
|
|
|
|
public static String iamApi( String SecretAccessKey,String AccessKeyID) throws Exception {
|
|
|
|
// 请求地址
|
|
|
|
String endpoint = "iam.volcengineapi.com";
|
|
|
|
String path = "/"; // 路径,不包含 Query// 请求接口信息
|
|
|
|
String service = "iam";
|
|
|
|
String region = "cn-beijing";
|
|
|
|
String schema = "https";
|
|
|
|
Sign sign = new Sign(region, service, schema, endpoint, path, AccessKeyID, SecretAccessKey);
|
|
|
|
|
|
|
|
String action = "ListPolicies";
|
|
|
|
String version = "2018-01-01";
|
|
|
|
|
|
|
|
Date date = new Date();
|
|
|
|
HashMap<String, String> queryMap = new HashMap() {{
|
|
|
|
put("Limit", "1");
|
|
|
|
}};
|
|
|
|
|
|
|
|
String contentType = "application/x-www-form-urlencoded";
|
|
|
|
return sign.doRequest("POST", queryMap, null, date, action, version,contentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String doRequest(String method, Map<String, String> queryList, byte[] body,
|
|
|
|
Date date, String action, String version,String contentType) throws Exception {
|
|
|
|
if (body == null) {
|
|
|
|
body = new byte[0];
|
|
|
|
}
|
|
|
|
String xContentSha256 = hashSHA256(body);
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
|
|
|
|
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
|
|
|
|
String xDate = sdf.format(date);
|
|
|
|
String shortXDate = xDate.substring(0, 8);
|
|
|
|
|
|
|
|
|
|
|
|
String signHeader = "host;x-date;x-content-sha256;content-type";
|
|
|
|
|
|
|
|
|
|
|
|
SortedMap<String, String> realQueryList = new TreeMap<>(queryList);
|
|
|
|
realQueryList.put("Action", action);
|
|
|
|
realQueryList.put("Version", version);
|
|
|
|
StringBuilder querySB = new StringBuilder();
|
|
|
|
for (String key : realQueryList.keySet()) {
|
|
|
|
querySB.append(signStringEncoder(key)).append("=").append(signStringEncoder(realQueryList.get(key))).append("&");
|
|
|
|
}
|
|
|
|
querySB.deleteCharAt(querySB.length() - 1);
|
|
|
|
|
|
|
|
String canonicalStringBuilder = method + "\n" + path + "\n" + querySB + "\n" +
|
|
|
|
"host:" + host + "\n" +
|
|
|
|
"x-date:" + xDate + "\n" +
|
|
|
|
"x-content-sha256:" + xContentSha256 + "\n" +
|
|
|
|
"content-type:" + contentType + "\n" +
|
|
|
|
"\n" +
|
|
|
|
signHeader + "\n" +
|
|
|
|
xContentSha256;
|
|
|
|
|
|
|
|
System.out.println(canonicalStringBuilder);
|
|
|
|
|
|
|
|
String hashcanonicalString = hashSHA256(canonicalStringBuilder.getBytes());
|
|
|
|
String credentialScope = shortXDate + "/" + region + "/" + service + "/request";
|
|
|
|
String signString = "HMAC-SHA256" + "\n" + xDate + "\n" + credentialScope + "\n" + hashcanonicalString;
|
|
|
|
|
|
|
|
byte[] signKey = genSigningSecretKeyV4(sk, shortXDate, region, service);
|
|
|
|
String signature = formatHex(hmacSHA256(signKey, signString));
|
|
|
|
|
|
|
|
|
|
|
|
URL url = new URL(schema + "://" + host + path + "?" + querySB);
|
|
|
|
|
|
|
|
|
|
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
|
conn.setRequestMethod(method);
|
|
|
|
conn.setRequestProperty("Host", host);
|
|
|
|
conn.setRequestProperty("X-Date", xDate);
|
|
|
|
conn.setRequestProperty("X-Content-Sha256", xContentSha256);
|
|
|
|
conn.setRequestProperty("Content-Type", contentType);
|
|
|
|
conn.setRequestProperty("Authorization", "HMAC-SHA256" +
|
|
|
|
" Credential=" + ak + "/" + credentialScope +
|
|
|
|
", SignedHeaders=" + signHeader +
|
|
|
|
", Signature=" + signature);
|
|
|
|
if (!Objects.equals(conn.getRequestMethod(), "GET")) {
|
|
|
|
conn.setDoOutput(true);
|
|
|
|
OutputStream os = conn.getOutputStream();
|
|
|
|
os.write(body);
|
|
|
|
os.flush();
|
|
|
|
os.close();
|
|
|
|
}
|
|
|
|
conn.connect();
|
|
|
|
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
|
|
|
|
InputStream is;
|
|
|
|
if (responseCode == 200) {
|
|
|
|
is = conn.getInputStream();
|
|
|
|
} else {
|
|
|
|
is = conn.getErrorStream();
|
|
|
|
}
|
|
|
|
byte[] bytes = toByteArray(is);
|
|
|
|
String responseBody = new String(bytes, StandardCharsets.UTF_8);
|
|
|
|
is.close();
|
|
|
|
|
|
|
|
System.out.println(responseCode);
|
|
|
|
System.out.println(responseBody);
|
|
|
|
return responseBody;
|
|
|
|
}
|
|
|
|
public static byte[] toByteArray(InputStream in) throws IOException {
|
|
|
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
|
|
|
byte[] data = new byte[4096];
|
|
|
|
int nRead;
|
|
|
|
while ((nRead = in.read(data, 0, data.length)) != -1) {
|
|
|
|
buffer.write(data, 0, nRead);
|
|
|
|
}
|
|
|
|
return buffer.toByteArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String signStringEncoder(String source) {
|
|
|
|
if (source == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
StringBuilder buf = new StringBuilder(source.length());
|
|
|
|
ByteBuffer bb = UTF_8.encode(source);
|
|
|
|
while (bb.hasRemaining()) {
|
|
|
|
int b = bb.get() & 255;
|
|
|
|
if (URLENCODER.get(b)) {
|
|
|
|
buf.append((char) b);
|
|
|
|
} else if (b == 32) {
|
|
|
|
buf.append("%20");
|
|
|
|
} else {
|
|
|
|
buf.append("%");
|
|
|
|
char hex1 = CONST_ENCODE.charAt(b >> 4);
|
|
|
|
char hex2 = CONST_ENCODE.charAt(b & 15);
|
|
|
|
buf.append(hex1);
|
|
|
|
buf.append(hex2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String hashSHA256(byte[] content) throws Exception {
|
|
|
|
try {
|
|
|
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
|
|
|
|
|
|
return formatHex(md.digest(content));
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new Exception(
|
|
|
|
"Unable to compute hash while signing request: "
|
|
|
|
+ e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static byte[] hmacSHA256(byte[] key, String content) throws Exception {
|
|
|
|
try {
|
|
|
|
Mac mac = Mac.getInstance("HmacSHA256");
|
|
|
|
mac.init(new SecretKeySpec(key, "HmacSHA256"));
|
|
|
|
return mac.doFinal(content.getBytes());
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new Exception(
|
|
|
|
"Unable to calculate a request signature: "
|
|
|
|
+ e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private byte[] genSigningSecretKeyV4(String secretKey, String date, String region, String service) throws Exception {
|
|
|
|
byte[] kDate = hmacSHA256((secretKey).getBytes(), date);
|
|
|
|
byte[] kRegion = hmacSHA256(kDate, region);
|
|
|
|
byte[] kService = hmacSHA256(kRegion, service);
|
|
|
|
return hmacSHA256(kService, "request");
|
|
|
|
}
|
|
|
|
|
|
|
|
private static final char[] HEX_LOWER = "0123456789abcdef".toCharArray();
|
|
|
|
|
|
|
|
/** 等同于 HexFormat.of().formatHex(bytes) */
|
|
|
|
public static String formatHex(byte[] bytes) {
|
|
|
|
Objects.requireNonNull(bytes, "bytes");
|
|
|
|
char[] out = new char[bytes.length * 2];
|
|
|
|
int j = 0;
|
|
|
|
for (byte b : bytes) {
|
|
|
|
int v = b & 0xFF;
|
|
|
|
out[j++] = HEX_LOWER[v >>> 4];
|
|
|
|
out[j++] = HEX_LOWER[v & 0x0F];
|
|
|
|
}
|
|
|
|
return new String(out);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 等同于 HexFormat.of().formatHex(bytes, offset, length) */
|
|
|
|
public static String formatHex(byte[] bytes, int offset, int length) {
|
|
|
|
Objects.requireNonNull(bytes, "bytes");
|
|
|
|
if (offset < 0 || length < 0 || offset + length > bytes.length) {
|
|
|
|
throw new IndexOutOfBoundsException(
|
|
|
|
"offset=" + offset + ", length=" + length + ", bytes.length=" + bytes.length);
|
|
|
|
}
|
|
|
|
char[] out = new char[length * 2];
|
|
|
|
int j = 0;
|
|
|
|
for (int i = offset; i < offset + length; i++) {
|
|
|
|
int v = bytes[i] & 0xFF;
|
|
|
|
out[j++] = HEX_LOWER[v >>> 4];
|
|
|
|
out[j++] = HEX_LOWER[v & 0x0F];
|
|
|
|
}
|
|
|
|
return new String(out);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 等同于 HexFormat.of().formatHex(buffer),不改变原 buffer 的 position/limit */
|
|
|
|
public static String formatHex(ByteBuffer buffer) {
|
|
|
|
Objects.requireNonNull(buffer, "buffer");
|
|
|
|
ByteBuffer dup = buffer.asReadOnlyBuffer();
|
|
|
|
byte[] data = new byte[dup.remaining()];
|
|
|
|
dup.get(data);
|
|
|
|
return formatHex(data);
|
|
|
|
}
|
|
|
|
} |
|
|
\ No newline at end of file |
...
|
...
|
|