您现在的位置是:首页 >学无止境 >Qt C++通过网络使用MinIO网站首页学无止境
Qt C++通过网络使用MinIO
简介qt 如何使用minio
本文是windows10上的Qt桌面应用,因为MinIO的CPP编译一直没有通过,所以本人换了一种方式来间接使用MinIO上传下载和删除文件。(本应用是在局域网内)
操作思路:首先在Java后端写好MinIO的文件上传下载和删除接口,然后在Qt端使用网络访问Java后端,从而实现文件的上传下载和删除。
本文要求要在服务器电脑上先安装好MinIO服务,并且开启服务;另外把java1.8环境配置好,后面需要把java的代码运行在此服务器电脑上。安装和配置教程可自行百度。
直接上代码
Qt代码
Qt5.12,所用模块需要添加network;
MinIORW.h头文件代码片段
#include <QString>
#include <QObject>
#pragma once
class MinIORW :public QObject
{
//这里用到了信号与槽,所以要写下面这个参数
Q_OBJECT
public:
MinIORW() {};
bool insertFileToMinIO(const QString& filePath, const QString& fileNewName, const QString& IP);
bool downloadFileFromServer(const QString& fileName, const QString& savePath, const QString& IP);
bool DeleteFileFromMinIO(const QString& fileName, const QString& IP);
};
MinIORW.cpp文件代码片段
#include "MinIORW.h"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QUrlQuery>
#include <QJsonDocument>
#include <QJsonObject>
#include <QHttpMultiPart>
#include <QFile>
#include <QFileInfo>
#include <QFileDialog>
#include <QEventLoop>
#pragma execution_character_set("utf-8") //防止中文乱码
//filePath:文件的绝对路径
//date:给文件加个前缀(可用可不用) 例如20250207_fileName.txt
//IP:MinIO服务器的地址
bool MinIORW::insertFileToMinIO(const QString& filePath, const QString& date, const QString& IP)
{
qDebug() << __FUNCTION__;
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QEventLoop loop;//这个是用来阻塞主进程,等待网络请求操作完成然后返回true或false
bool uploadSuccess = false;
QNetworkRequest request;
//下面是JAVA后端的接口名称,需要换成你自己的
request.setUrl(QUrl("http://" + IP + ":8081/minioOpr/insertMinIOObject"));
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QFile* file = new QFile(filePath);//通过文件的绝对路径,读取文件数据
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << "Could not open the file for reading";
return false;
}
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="file"; filename="" + date + "_" + QFileInfo(file->fileName()).fileName() + """));
filePart.setBodyDevice(file);
multiPart->append(filePart);
QNetworkReply* reply = manager->post(request, multiPart);
//[&]符号,表示此槽函数内可以修改uploadSuccess 的值
QObject::connect(reply, &QNetworkReply::finished, [&]() {
//reply->deleteLater();
//file->deleteLater();
//multiPart->deleteLater();
if (reply->error() == QNetworkReply::NoError) {
qDebug() << "File uploaded successfully:" << reply->readAll();
uploadSuccess = true;
}
else {
qDebug() << "Error:" << reply->errorString();
uploadSuccess = false;
}
loop.quit();
});
loop.exec();//开始阻塞,等待quit()运行,即可以接着运行,不然uploadSuccess的值无法使用
reply->deleteLater();
file->deleteLater();
multiPart->deleteLater();
return uploadSuccess;
}
//根据文件名fileName来下载MinIO中的文件
//savePath:下载文件到指定的路径下,例如:C:UsersDJMDesktop20250207_test.txt
//IP:MinIO服务器的地址
bool MinIORW::downloadFileFromServer(const QString& fileName, const QString& savePath, const QString& IP)
{
qDebug() << __FUNCTION__ << fileName << savePath;
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QEventLoop loop;
bool downloadSuccess = false;
// 构建请求URL,这里假设Java后端有一个名为/download的端点
QUrl url("http://" + IP + ":8081/minioOpr/getMinIOObject");//?fileName+ QUrl::toPercentEncoding(fileName)
//打包请求参数赋值
QJsonObject json;
json["fileName"] = fileName;
QJsonDocument doc(json);
QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
// 创建QNetworkRequest对象并设置URL
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); // 设置内容类型为JSON
// 发送GET请求
QNetworkReply* reply = manager->post(request, jsonData);
// 连接信号和槽,处理响应
connect(reply, &QNetworkReply::finished, [&]() {
if (reply->error() == QNetworkReply::NoError) {
// 读取响应数据
QByteArray fileData = reply->readAll();
// 将数据写入到本地文件
QFile file(savePath);
if (file.open(QIODevice::WriteOnly)) {
file.write(fileData);
file.close();
qDebug() << "File downloaded and saved to" << savePath;
downloadSuccess = true;
}
else {
qDebug() << "Failed to open file for writing:" << savePath;
downloadSuccess = false;
}
}
else {
qDebug() << "Error downloading file:" << reply->errorString();
downloadSuccess = false;
}
loop.quit();
// 清理
//reply->deleteLater();
//manager->deleteLater();
});
loop.exec();
reply->deleteLater();
manager->deleteLater();
return downloadSuccess;
}
//根据文件名fileName来删除MinIO中的文件
//IP:MinIO服务器的地址
bool MinIORW::DeleteFileFromMinIO(const QString& fileName, const QString& IP)
{
qDebug() << __FUNCTION__;
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QEventLoop loop;
bool deleteSuccess = false;
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QJsonObject json;
json["fileName"] = fileName;
QJsonDocument doc(json);
QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
// 创建QNetworkRequest对象并设置URL
QUrl url("http://" + IP + ":8081/minioOpr/delMinIOObject");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); // 设置内容类型为JSON
// 发送GET请求
QNetworkReply* reply = manager->post(request, jsonData);
QObject::connect(reply, &QNetworkReply::finished, [&]() {
//reply->deleteLater();
//multiPart->deleteLater();
if (reply->error() == QNetworkReply::NoError) {
qDebug() << "File uploaded successfully:" << reply->readAll();
deleteSuccess = true;
}
else {
qDebug() << "Error:" << reply->errorString();
deleteSuccess = false;
}
loop.quit();
});
loop.exec();
reply->deleteLater();
multiPart->deleteLater();
return deleteSuccess;
}
Java代码
本文使用的是java1.8;8.5.16的minio;
yml文件代码
# 应用服务 WEB 访问端口
server:
port: 8081
# Spring Boot 应用配置
spring:
application:
name: springboot-minio
servlet:
multipart:
max-file-size: 128MB # 单个文件的最大大小
max-request-size: 512MB # 整个请求的最大大小
pom文件部分依赖
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.16</version>
</dependency>
MinioClient配置文件
package com.javaminio.configuration;
import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean
public MinioClient minioClient(){
//链式编程,构建MinIOClient对象
return MinioClient.builder().endpoint("http://127.0.0.1:9000/")
.credentials("admin","jszx123!")
.build();
}
}
controller层代码
package com.javaminio.controller;
import com.javaminio.result.R;
import com.javaminio.service.MinIORWService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Objects;
@RestController
@CrossOrigin
@RequestMapping("/minioOpr")
public class MinIORWController {
@Resource
private MinIORWService minIORWService;
@GetMapping(value="/getMinIOObjList")
public R getMinIOObjList(){
return R.OK(minIORWService.getObjects());
}
//插入
@PostMapping(value="/insertMinIOObject")
public R insertMinIOObject(MultipartFile file) throws Exception {
return R.OK(minIORWService.insertData(file));
}
//获取文件
@PostMapping(value="/getMinIOObject")
public void getMinIOObject(@RequestBody Map<String,Object> map, HttpServletResponse response) throws Exception {
try {
String fileName = map.get("fileName").toString();
if(fileName.isEmpty()){
return;
}
// 从MinIO获取文件(这里省略了具体的bucket名称和获取文件的逻辑)
// 假设你有一个方法可以从MinIO下载文件并返回其内容的字节数组
byte[] fileBytes = minIORWService.getObject(fileName);
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="" + fileName + """);
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setContentLength(fileBytes.length);
response.getOutputStream().write(fileBytes);
} catch (Exception e) {
throw e;
}
}
//删除文件
@PostMapping(value="/delMinIOObject")
public R delMinIOObject(@RequestBody Map<String,Object> map) throws Exception {
String fileName = map.get("fileName").toString();
if(Objects.equals(fileName, "") || fileName==null){
return R.fail();
}
return R.OK(minIORWService.deleteObject(fileName));
}
}
R文件代码
package com.javaminio.result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class R {
private int code;
private String msg;
private Object data;
public static R OK(){
return new R(200,"成功",null);
}
public static R OK(Object data){
return new R(200,"成功",data);
}
public static R fail(){
return new R(500,"失败",null);
}
}
service层代码
package com.javaminio.service;
import io.minio.StatObjectResponse;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
public interface MinIORWService {
List<String> getObjects();
boolean insertData(MultipartFile file)throws Exception;
StatObjectResponse getObjStat(String fileName) throws Exception;
byte[] getObject(String fileName) throws Exception;
boolean deleteObject(String fileName) throws Exception;
}
serviceImpl层代码
package com.javaminio.service.impl;
import com.javaminio.service.MinIORWService;
import io.minio.*;
import io.minio.messages.Item;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
@Service
public class MinIORWServiceImpl implements MinIORWService {
@Resource
private MinioClient minioClient;
public List<String> getObjects(){
// Iterable<Result<Item>> listObjects = minioClient.listObjects(ListObjectsArgs.builder()
// .bucket("jszx").build());
// List<String> list = new ArrayList<>();
// listObjects.forEach(itemResult -> {
// try {
// Item item = itemResult.get();
// System.out.println(item.objectName());
// list.add(item.objectName());
// }catch (Exception e){
// throw new RuntimeException();
// }
// });
// return list;
// 用于存储文件名的列表
List<String> objectNames = new ArrayList<>();
try {
// 列出存储桶中的所有对象
Iterable<Result<Item>> objects = minioClient.listObjects(ListObjectsArgs.builder().bucket("jszx").build());
// 遍历结果并添加文件名到列表中
for (Result<Item> result : objects) {
Item item = result.get();
objectNames.add(item.objectName());
System.out.println("File name: " + item.objectName());
}
} catch (Exception e) {
e.printStackTrace();
// 根据需要处理异常,例如记录日志或抛出运行时异常
throw new RuntimeException("Error occurred while listing objects in bucket jszx", e);
}
return objectNames;
}
public boolean insertData(MultipartFile file) throws Exception{
try {
boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket("jszx").build());
if(!isExist){
minioClient.makeBucket(MakeBucketArgs.builder().bucket("jszx").build());//创建桶
}
// 将MultipartFile转换为InputStream
InputStream inputStream = file.getInputStream();
String objectName = file.getOriginalFilename(); // 可以根据需要修改对象名称
//放文件
ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs
.builder()
.bucket("jszx").object(objectName)
.stream(inputStream, file.getSize(), -1)
.build());
System.out.println(objectWriteResponse);
return true;
}catch (Exception e){
throw e;
}
}
public byte[] getObject(String fileName) throws Exception{
GetObjectResponse getObjectResponse = minioClient.getObject(
GetObjectArgs.builder()
.bucket("jszx")
.object(fileName)
.build());
// 将文件内容读取到byte数组中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = getObjectResponse.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
return baos.toByteArray();
}
public StatObjectResponse getObjStat(String fileName) throws Exception{
return minioClient.statObject(StatObjectArgs
.builder()
.bucket("jszx")
.object(fileName)
.build());
}
public boolean deleteObject(String fileNames) throws Exception{
boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket("jszx").build());
if(!isExist){
return false;
}
String[] fileName = fileNames.split(",");
for(int i=0;i< fileName.length;i++){
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket("jszx").object(fileName[i]).build());
}
return true;
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。