之前做的一个图片识别系统,需要调用深度学习模型,并且对识别的结果进行长期保存。Java与python通信可通过http实现,对于识别结果的保存可放在云端。
整体思路:Java(客户端)将图片上传至阿里云oss,本地数据库只保存图片在阿里云oss中的路径,Java(客户端)将图片路径通过http方式发送至python(服务端),python(服务端)拿到图片路径后将其下载到本地,并调用深度学习模型进行图像处理,将处理结果上传至阿里云oss,并发送给Java(客户端),最后python(服务端)将本地的图片删除。
Java客户端
引入maven坐标
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
实现upload接口
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* 此处代码仅为了方便分享,
* 在实际开发中请遵循开发规范,将业务逻辑处理部分移入service层
*
*/
@RestController
public class UploadController {
/**
* 配置你的阿里云OSS信息
*
*/
//注意此处endpoint不能有空格,且为双反斜线 https:// oss-cn-hangzhou.aliyuncs.co(X)https:/oss-cn-hangzhou.aliyuncs.co(X)
private static final String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
private static final String accessKeyId = "LTAI5y7LisfinxKNXHWnNx";
private static final String accessKeySecret = "JezLnZNFENXSIWDTOif";
private static final String bucketName = "13187082671";
@PostMapping("/upload")
public void upload(MultipartFile image) throws IOException {
//【1】将图片上传到阿里云oss
//获取上传的文件的输入流
InputStream inputStream = image.getInputStream();
//原始文件名
String originalFilename = image.getOriginalFilename();
//截取原始文件名的后缀 Ding_ZG.jpg
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//构造新文件名称 e9392461-0c72-4a7a-a44c-4621be7b0246.jpg
String objectName = UUID.randomUUID().toString() + extension;
//创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//上传文件到 OSS
ossClient.putObject(bucketName, objectName, inputStream);
//文件访问路径规则 https://BucketName.Endpoint/ObjectName
String image_url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
System.out.println(image_url);
/**
* 此处可做持久化,将image_url存入数据库
* 如:Image image = new image();
* image.setimageUrl(image_url);
* */
//关闭ossClient
ossClient.shutdown();
//【2】将图片路径发送给服务端
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 创建一个 POST 请求对象,指定要访问的 URL
HttpPost httpPost = new HttpPost("http://localhost:8765");
// 创建请求的消息体(图片在阿里云oss中的路径),并设置编码格式为 UTF-8
StringEntity entity = new StringEntity(image_url);
// 将请求的消息体设置到 POST 请求中
httpPost.setEntity(entity);
// 设置请求头,指定消息体的类型为纯文本,并指定编码格式为 UTF-8
httpPost.setHeader("Content-type", "text/plain; charset=UTF-8");
// 发送请求并获取响应
String response_url = EntityUtils.toString(httpClient.execute(httpPost).getEntity());
// 输出响应内容
System.out.println(response_url);
/**
* 此处可做持久化,将response_url存入数据库
* 如:image.setresponseUrl(response_url);
*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
Python服务端
import os
import oss2
import uuid
from http.server import BaseHTTPRequestHandler, HTTPServer
# 配置你的阿里云OSS信息
access_key_id = 'LTAI5tAAKNDISIRDXNKAMAK7LKTx'
access_key_secret = 'JezLnVSKEFEIWENSNonVrbOif'
endpoint = 'oss-cn-hangzhou.aliyuncs.com'
bucket_name = '13187082671'
# 创建OSS存储空间对象
auth = oss2.Auth(access_key_id, access_key_secret)
bucket = oss2.Bucket(auth, endpoint, bucket_name)
class HttpRequestTest(BaseHTTPRequestHandler):
def do_POST(self):
# 【1】获取客户端发来的图片路径
# 获取请求头中的 Content-Length 字段,表示请求体的长度
content_length = int(self.headers['Content-Length'])
# 读取请求体数据(接受到的图片路径),并转换为 UTF-8 编码的字符串类型
image_url = self.rfile.read(content_length).decode('UTF-8')
# 打印接受到的图片路径
print(image_url)
#得到图片名称 e9392461-0c72-4a7a-a44c-4621be7b0246.png
image_url = image_url[-40:]
print(image_url)
local_image = 'D://test.jpg' # 保存到本地的文件名,这个也是你模型需要输入的
# 下载图片
bucket.get_object_to_file(image_url, local_image)
print("图片下载完成!")
# 【2】调用模型,并获得输出结果
# ---------------------------------------------------------#
# 此处调用你自己的模型算法
# 假设模型输出结果为test_image = 'E://test.jpg'
test_image = 'E://test.jpg'
# ---------------------------------------------------------#
# 【3】将输出结果上传到阿里云oss
# 截取后缀
extension = test_image[-4:]
# 新文件名
upload_name = str(uuid.uuid4())+ extension
# 重命名文件
new_local_file = os.path.splitext(test_image)[0] + os.path.splitext(upload_name)[1]
os.rename(test_image, new_local_file)
# 上传图片
bucket.put_object_from_file(upload_name, new_local_file)
# 获取上传后的图片URL
image_url = f'https://{bucket_name}.{endpoint}/{upload_name}'
print(image_url)
# 【4】将结果发送给客户端
# 设置响应状态码为 200
self.send_response(200)
# 设置响应头,指定响应类型为纯文本,并指定编码格式为 UTF-8
self.send_header('Content-type', 'text/plain; charset=utf-8')
# 结束响应头的设置
self.end_headers()
# 发送响应,模型处理后的图片路径发送到客户端
self.wfile.write(image_url.encode('utf-8'))
print("发送完成!!")
# 将保存在本地的图片删除
os.remove(local_image)
os.remove(test_image)
print("删除成功!!")
if __name__ == "__main__":
server_address = ('localhost', 8765)
httpd = HTTPServer(server_address, HttpRequestTest)
print('启动服务器...')
# 启动服务器并持续监听请求
httpd.serve_forever()