diff --git a/pom.xml b/pom.xml
index 3cb0a6b..52be934 100644
--- a/pom.xml
+++ b/pom.xml
@@ -486,6 +486,12 @@
rsyntaxtextarea
3.3.4
+
+
+ org.apache.tika
+ tika-core
+ 1.27
+
diff --git a/src/main/java/com/zhangmeng/tools/controller/MinioUploadController.java b/src/main/java/com/zhangmeng/tools/controller/MinioUploadController.java
index 2aacada..90039de 100644
--- a/src/main/java/com/zhangmeng/tools/controller/MinioUploadController.java
+++ b/src/main/java/com/zhangmeng/tools/controller/MinioUploadController.java
@@ -2,18 +2,23 @@ package com.zhangmeng.tools.controller;
import cn.hutool.crypto.digest.DigestUtil;
-import com.zhangmeng.tools.utils.AlertUtils;
-import com.zhangmeng.tools.utils.EncryptUtils;
-import com.zhangmeng.tools.utils.ImagePath;
-import com.zhangmeng.tools.utils.MinioUtils;
+import com.zhangmeng.tools.dto.BucketFile;
+import com.zhangmeng.tools.utils.*;
+import io.minio.messages.Bucket;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
import javafx.fxml.FXML;
-import javafx.scene.control.Button;
-import javafx.scene.control.TextField;
+import javafx.scene.Scene;
+import javafx.scene.control.*;
+import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
-import javafx.stage.DirectoryChooser;
-import javafx.stage.FileChooser;
-import javafx.stage.Stage;
+import javafx.scene.text.Text;
+import javafx.stage.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
@@ -21,6 +26,10 @@ import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
/**
* 大文件上传
@@ -41,9 +50,6 @@ public class MinioUploadController {
@FXML
public TextField secretKey;
- @FXML
- public TextField bucket;
-
@FXML
public ImageView iv;
@@ -56,9 +62,140 @@ public class MinioUploadController {
@FXML
public TextField file_path;
+ @FXML
+ public ComboBox backet_list;
+
+ private final ObservableList backet_item_list = FXCollections.observableArrayList();
+ private final ObservableList list = FXCollections.observableArrayList();
+
+ @FXML
+ public TableView tableview;
+
+ @FXML
+ public TableColumn file_name;
+
+ @FXML
+ public TableColumn file_size;
+
+ @FXML
+ public TableColumn file_url;
+
+ @FXML
+ public TableColumn file_bucket;
+
+ @FXML
+ public Button reload_config;
+
+ @FXML
+ public Button delete_bucket;
+
+ @FXML
+ public Button create_bucket;
+
+ @FXML
+ public TextField create_bucket_name;
+
+ public void reload(String bucketName){
+ if (bucketName == null){
+ return;
+ }
+ List bucketFiles = MinioUtils.getFileList(bucketName);
+ if (bucketFiles.size()>0){
+ list.clear();
+ list.addAll(bucketFiles);
+ }
+ }
+
+
+ public void init_bucket_list(){
+ backet_item_list.clear();
+ //获取所有储存桶
+ List buckets = MinioUtils.getAllBuckets();
+ if (buckets.size()>0){
+ for (Bucket bucket : buckets) {
+ backet_item_list.add(bucket.name());
+ }
+ }
+
+ }
+
+ public void init_minio_config(){
+ //默认值
+ endpoint.setText("http://192.168.1.254:9000");
+ accessKey.setText("minioadmin");
+ secretKey.setText("minioadmin");
+ MinioUtils.objectMap.put("endpoint",endpoint.getText());
+ MinioUtils.objectMap.put("accessKey",accessKey.getText());
+ MinioUtils.objectMap.put("secretKey",secretKey.getText());
+ }
+
+ public void reload_minio_config(){
+
+ }
+
@FXML
public void initialize() {
+ init_minio_config();
+
+ this.backet_list.setItems(backet_item_list);
+ backet_list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
+ @Override
+ public void changed(ObservableValue extends String> observable, String oldValue, String newValue) {
+ if (newValue != null){
+ reload(newValue);
+ }
+ }
+ });
+ init_bucket_list();
+
+ tableview.setItems(list);
+ file_name.setCellValueFactory(new PropertyValueFactory("fileName"));
+ file_size.setCellValueFactory(new PropertyValueFactory("size"));
+ file_url.setCellValueFactory(new PropertyValueFactory("url"));
+ file_bucket.setCellValueFactory(new PropertyValueFactory("bucketName"));
+
+ file_name.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
+ file_size.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
+ file_url.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
+ file_bucket.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
+
+ // 创建上下文菜单
+ final ContextMenu contextMenu = new ContextMenu();
+ MenuItem cat = new MenuItem("查看");
+ MenuItem copy_url = new MenuItem("复制url");
+ MenuItem menuItem = new MenuItem("删除");
+ menuItem.setOnAction(event -> {
+ list.remove(tableview.getSelectionModel().getSelectedItem());
+ });
+ contextMenu.getItems().add(cat);
+ cat.setOnAction(event -> {
+ BucketFile selectedItem = tableview.getSelectionModel().getSelectedItem();
+ iv.setImage(new Image(selectedItem.getUrl()));
+ });
+ contextMenu.getItems().add(copy_url);
+ copy_url.setOnAction(event -> {
+ ClipboardUtils.setString(tableview.getSelectionModel().getSelectedItem().getUrl());
+ });
+
+ contextMenu.getItems().add(menuItem);
+ // 添加事件监听器来处理上下文菜单的显示
+ tableview.setOnContextMenuRequested(event -> {
+ // 只有当表格有选中项时才显示上下文菜单
+ if (!tableview.getSelectionModel().isEmpty()) {
+ contextMenu.show(tableview, event.getScreenX(), event.getScreenY());
+ }
+ });
+
+ tableview.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
+ @Override
+ public void changed(ObservableValue extends BucketFile> observable, BucketFile oldValue, BucketFile newValue) {
+ if (newValue != null) {
+ System.out.println(newValue.getFileName());
+ }
+ }
+ });
+
file_choose.setText(null);
ImageView iv = new ImageView(new Image(ImagePath.path(ImagePath.ImagePathType.IMAGE_FILE)));
iv.setPreserveRatio(true);
@@ -66,11 +203,6 @@ public class MinioUploadController {
file_choose.setGraphic(iv);
file_choose.setOnAction(event -> choose_file());
- //默认值
- endpoint.setText("http://192.168.1.14:9000");
- accessKey.setText("minioadmin");
- secretKey.setText("minioadmin");
- bucket.setText("mediafiles");
upload.setOnAction(event -> {
@@ -89,19 +221,62 @@ public class MinioUploadController {
return;
}
- if (bucket.getText().length() == 0) {
- AlertUtils.alert_warning("bucket不能为空!");
+ if (backet_list.getSelectionModel().getSelectedItem() == null) {
+ AlertUtils.alert_warning("请选择bucket再试!");
return;
}
File file = new File(file_path.getText());
- String extension = FilenameUtils.getExtension(file.getName());
- if (extension.equals("jpg") || extension.equals("png")) {
- images_upload();
+// String extension = FilenameUtils.getExtension(file.getName());
+// if (extension.equals("jpg") || extension.equals("png")) {
+// images_upload();
+// }
+// if (extension.equals("mp4") || extension.equals("avi")) {
+// videos_upload();
+// }
+
+ MinioUtils.upload_file(file,backet_list.getSelectionModel().getSelectedItem());
+ reload(backet_list.getSelectionModel().getSelectedItem());
+ });
+
+ reload_config.setOnAction(event -> {
+
+ });
+
+ create_bucket.setOnAction(event -> {
+ if (create_bucket_name.getText().length() == 0) {
+ AlertUtils.alert_warning("bucket的名称不能为空!");
+ return;
}
- if (extension.equals("mp4") || extension.equals("avi")) {
- videos_upload();
+ MinioUtils.createBucket(create_bucket_name.getText());
+ init_bucket_list();
+ });
+ delete_bucket.setOnAction(event -> {
+
+ // 用户点击了确定按钮
+ if (backet_list.getSelectionModel().getSelectedItem() == null){
+ MinioUtils.warning_msg("请选择将要删除的bucket在试!");
+ return;
}
+ Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
+ alert.initModality(Modality.APPLICATION_MODAL);
+ alert.setTitle("确认");
+ alert.setHeaderText("你确定要继续吗?");
+ alert.setContentText("这将执行一个操作。");
+ Optional result = alert.showAndWait();
+ result.ifPresent(response -> {
+ if (response == ButtonType.OK) {
+ //清空
+ List fileList = MinioUtils.getFileList(backet_list.getSelectionModel().getSelectedItem());
+ List del_list = fileList.stream().map(BucketFile::getFileName).collect(Collectors.toList());
+
+ MinioUtils.removeFiles(backet_list.getSelectionModel().getSelectedItem(), del_list);
+ MinioUtils.removeBucket(backet_list.getSelectionModel().getSelectedItem());
+ AlertUtils.alert_msg("删除成功!");
+ init_bucket_list();
+ } else {
+ }
+ });
});
}
@@ -116,14 +291,14 @@ public class MinioUploadController {
// process the chunk
String fileMd5 = DigestUtil.md5Hex(chunk);
//判断分块是否存在
- if (!MinioUtils.checkChunk(fileMd5, i, bucket.getText())) {
+ if (!MinioUtils.checkChunk(fileMd5, i, backet_list.getSelectionModel().getSelectedItem())) {
//得到分块文件的目录路径
String chunkFileFolderPath = MinioUtils.getChunkFileFolderPath(fileMd5);
//得到分块文件的路径
String chunkFilePath = chunkFileFolderPath + i;
try {
//将文件存储至minIO
- MinioUtils.addMediaFilesToMinIO(chunk, bucket.getText(), chunkFilePath, "application/octet-stream");
+ MinioUtils.addMediaFilesToMinIO(chunk, backet_list.getSelectionModel().getSelectedItem(), chunkFilePath, "application/octet-stream");
} catch (Exception ex) {
ex.printStackTrace();
}
@@ -136,7 +311,7 @@ public class MinioUploadController {
try {
//上传文件到minIO
- MinioUtils.addMediaFilesToMinIO(filereader.getFile().getAbsolutePath(), bucket.getText(), mergeFilePath);
+ MinioUtils.addMediaFilesToMinIO(filereader.getFile().getAbsolutePath(), backet_list.getSelectionModel().getSelectedItem(), mergeFilePath);
log.debug("合并文件上传MinIO完成{}", filereader.getFile().getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
@@ -156,7 +331,7 @@ public class MinioUploadController {
String md5Hex = DigestUtil.md5Hex(bytes);
String contentType = Files.probeContentType(file.toPath());
String extension = FilenameUtils.getExtension(file.getName());
- MinioUtils.addMediaFilesToMinIO(bytes, bucket.getText(), md5Hex + "." + extension, contentType);
+ MinioUtils.addMediaFilesToMinIO(bytes, backet_list.getSelectionModel().getSelectedItem(), md5Hex + "." + extension, contentType);
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/src/main/java/com/zhangmeng/tools/dto/BucketFile.java b/src/main/java/com/zhangmeng/tools/dto/BucketFile.java
new file mode 100644
index 0000000..b0e53fd
--- /dev/null
+++ b/src/main/java/com/zhangmeng/tools/dto/BucketFile.java
@@ -0,0 +1,68 @@
+package com.zhangmeng.tools.dto;
+
+
+/**
+ * @author zhangmeng
+ * @version 1.0
+ * @date 2024-03-07 16:31
+ */
+
+public class BucketFile {
+
+ private String bucketName;
+ private String fileName;
+ private boolean isDir;
+ private Long size;
+ private String url;
+
+ public BucketFile() {
+ }
+
+ public BucketFile(String bucketName, String fileName, boolean isDir, Long size, String url) {
+ this.bucketName = bucketName;
+ this.fileName = fileName;
+ this.isDir = isDir;
+ this.size = size;
+ this.url = url;
+ }
+
+ public String getBucketName() {
+ return bucketName;
+ }
+
+ public void setBucketName(String bucketName) {
+ this.bucketName = bucketName;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public boolean isDir() {
+ return isDir;
+ }
+
+ public void setDir(boolean dir) {
+ isDir = dir;
+ }
+
+ public Long getSize() {
+ return size;
+ }
+
+ public void setSize(Long size) {
+ this.size = size;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
diff --git a/src/main/java/com/zhangmeng/tools/utils/MinioUtils.java b/src/main/java/com/zhangmeng/tools/utils/MinioUtils.java
index b8cf44a..d62f055 100644
--- a/src/main/java/com/zhangmeng/tools/utils/MinioUtils.java
+++ b/src/main/java/com/zhangmeng/tools/utils/MinioUtils.java
@@ -1,19 +1,30 @@
package com.zhangmeng.tools.utils;
-import io.minio.GetObjectArgs;
-import io.minio.MinioClient;
-import io.minio.PutObjectArgs;
-import io.minio.UploadObjectArgs;
+import com.zhangmeng.tools.dto.BucketFile;
+import io.minio.*;
+import io.minio.errors.*;
+import io.minio.http.Method;
+import io.minio.messages.Bucket;
+import io.minio.messages.DeleteObject;
+import io.minio.messages.Item;
+import javafx.application.Platform;
+import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.tika.Tika;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+import java.util.stream.Collectors;
@Slf4j
public class MinioUtils {
@@ -25,6 +36,35 @@ public class MinioUtils {
}
}
+ public static Map objectMap = new HashMap<>();
+ public static MinioClient getDefault() {
+ if (minioClient == null) {
+ Object endpoint = objectMap.get("endpoint");
+ Object accessKey = objectMap.get("accessKey");
+ Object secretKey = objectMap.get("secretKey");
+ if (endpoint == null ){
+ Platform.runLater(()->{
+ AlertUtils.alert_warning("配置文件:endpoint 为空");
+ });
+ return null;
+ }
+ if (accessKey == null ){
+ Platform.runLater(()->{
+ AlertUtils.alert_warning("配置文件:accessKey 为空");
+ });
+ return null;
+ }
+
+ if (secretKey == null ){
+ Platform.runLater(()->{
+ AlertUtils.alert_warning("配置文件:secretKey 为空");
+ });
+ return null;
+ }
+ minioClient = MinioClient.builder().endpoint(endpoint.toString()).credentials(accessKey.toString(), secretKey.toString()).build();
+ }
+ return minioClient;
+ }
public static String getFilePathByMd5(String fileMd5, String fileExt) {
return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + fileMd5 + fileExt;
@@ -56,6 +96,66 @@ public class MinioUtils {
return false;
}
+ public static List- getAllObjectsByPrefix(String bucketName,
+ String prefix,
+ boolean recursive) {
+ List
- list = new ArrayList<>();
+ Iterable> objectsIterator = getDefault().listObjects(
+ ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());
+ if (objectsIterator != null) {
+ for (Result
- o : objectsIterator) {
+ Item item = null;
+ try {
+ item = o.get();
+ } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
+ e.printStackTrace();
+ }
+ list.add(item);
+ }
+ }
+ return list;
+ }
+
+ public static List getFileList(String bucketName) {
+
+ List
- itemList = getAllObjectsByPrefix(bucketName, null, true);
+ List list = new ArrayList<>();
+ if (itemList.size() > 0 ){
+ list = itemList.stream().map(i -> {
+ BucketFile bucketFile = new BucketFile();
+ bucketFile.setBucketName(bucketName);
+ bucketFile.setDir(i.isDir());
+ bucketFile.setFileName(i.objectName());
+ bucketFile.setSize(i.size());
+ //获取url
+ String presignedObjectUrl = getPresignedObjectUrl(bucketName, i.objectName());
+ bucketFile.setUrl(presignedObjectUrl);
+ return bucketFile;
+ }).collect(Collectors.toList());
+ }
+ return list;
+ }
+
+ /**
+ * 获得文件外链
+ *
+ * @param bucketName
+ * @param objectName
+ * @return url
+ */
+ public static String getPresignedObjectUrl(String bucketName, String objectName) {
+ GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
+ .bucket(bucketName)
+ .object(objectName)
+ .method(Method.GET).build();
+ try {
+ return getDefault().getPresignedObjectUrl(args);
+ } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException | ServerException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
public static class FileChunkReader implements AutoCloseable {
private final FileChannel channel;
@@ -293,7 +393,159 @@ public class MinioUtils {
}
- public static void main(String[] args) {
- test("G:\\FXGL基础入门教程 Java游戏引擎教程_1简介与游戏演示\\1-1 简介与游戏演示-1080P 高清-AVC.mp4");
+ /**
+ * 获得所有Bucket列表
+ *
+ * @return
+ */
+ public static List getAllBuckets() {
+ try {
+ return getDefault().listBuckets();
+ } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static void upload_file(File file,String bucketName){
+ //文件名
+ String fileName = file.getName();
+ String newFileName = System.currentTimeMillis() + "." + StringUtils.substringAfterLast(fileName, ".");
+ String contentType = getContentType(file);
+ if (bucketName == null){
+ AlertUtils.alert_warning("上传的bucket不能为空!");
+ return;
+ }
+ uploadFile(bucketName, file, newFileName, contentType);
+ AlertUtils.alert_msg("文件上传成功");
+ }
+
+ /**
+ * 使用MultipartFile进行文件上传
+ *
+ * @param bucketName 存储桶
+ * @param file 文件名
+ * @param objectName 对象名
+ * @param contentType 类型
+ * @return
+ */
+ public static ObjectWriteResponse uploadFile(String bucketName, File file, String objectName, String contentType) {
+ FileInputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(file);
+ return minioClient.putObject(
+ PutObjectArgs.builder()
+ .bucket(bucketName)
+ .object(objectName)
+ .contentType(contentType)
+ .stream(inputStream,inputStream.available(), -1)
+ .build());
+ } catch (IOException | ServerException | InsufficientDataException | XmlParserException | InternalException | InvalidResponseException | InvalidKeyException | NoSuchAlgorithmException | ErrorResponseException e) {
+ e.printStackTrace();
+ } finally {
+ if (inputStream != null){
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return null;
+ }
+
+
+ public static String getContentType(File file){
+ Tika tika = new Tika();
+ try {
+ return tika.detect(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 启动SpringBoot容器的时候初始化Bucket
+ * 如果没有Bucket则创建
+ *
+ * @param bucketName
+ */
+ @SneakyThrows(Exception.class)
+ public static void createBucket(String bucketName) {
+ if (!bucketExists(bucketName)) {
+ getDefault().makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+ success_msg(bucketName + "创建成功!");
+ }else {
+ warning_msg(bucketName + "已存在");
+ }
+ }
+
+ public static void warning_msg(String msg){
+ Platform.runLater(()->{
+ AlertUtils.alert_warning(msg );
+ });
+ }
+
+ public static void success_msg(String msg){
+ Platform.runLater(()->{
+ AlertUtils.alert_msg(msg);
+ });
+ }
+
+ /**
+ * 判断Bucket是否存在,true:存在,false:不存在
+ *
+ * @param bucketName
+ * @return
+ */
+ @SneakyThrows(Exception.class)
+ public static boolean bucketExists(String bucketName) {
+ return getDefault().bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+ }
+
+ /**
+ * 根据bucketName删除Bucket,true:删除成功; false:删除失败,文件或已不存在
+ *
+ * @param bucketName
+ * @throws Exception
+ */
+ @SneakyThrows(Exception.class)
+ public static void removeBucket(String bucketName) {
+ getDefault().removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
+ }
+
+ /**
+ * 删除文件
+ *
+ * @param bucketName 存储桶
+ * @param objectName 文件名称
+ */
+ @SneakyThrows(Exception.class)
+ public static void removeFile(String bucketName, String objectName) {
+ minioClient.removeObject(
+ RemoveObjectArgs.builder()
+ .bucket(bucketName)
+ .object(objectName)
+ .build());
+ }
+
+ /**
+ * 批量删除文件
+ *
+ * @param bucketName 存储桶
+ * @param keys 需要删除的文件列表
+ * @return
+ */
+ public static void removeFiles(String bucketName, List keys) {
+ List objects = new LinkedList<>();
+ keys.forEach(s -> {
+ objects.add(new DeleteObject(s));
+ try {
+ removeFile(bucketName, s);
+ } catch (Exception e) {
+ log.error("[Minio工具类]>>>> 批量删除文件,异常:", e);
+ }
+ });
}
}
diff --git a/src/main/resources/fxml/minio-upload.fxml b/src/main/resources/fxml/minio-upload.fxml
index 328f1bb..d954577 100644
--- a/src/main/resources/fxml/minio-upload.fxml
+++ b/src/main/resources/fxml/minio-upload.fxml
@@ -1,32 +1,45 @@
+
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+