2023年9月20日18:20:14
parent
17c4c219ac
commit
ccf04aca91
|
|
@ -28,22 +28,20 @@ package com.zhangmeng.tools.controller;
|
||||||
import com.zhangmeng.tools.utils.ImagePath;
|
import com.zhangmeng.tools.utils.ImagePath;
|
||||||
import com.zhangmeng.tools.utils.ResourcesUtils;
|
import com.zhangmeng.tools.utils.ResourcesUtils;
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
import javafx.beans.value.ObservableValue;
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.scene.control.SplitPane;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.BorderPane;
|
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
|
|
@ -610,4 +608,12 @@ public class HomeController implements Serializable {
|
||||||
public void log_console_menu_item(ActionEvent actionEvent) {
|
public void log_console_menu_item(ActionEvent actionEvent) {
|
||||||
load_small_tools(18);
|
load_small_tools(18);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void edit_plus_code_menu_item(ActionEvent actionEvent) {
|
||||||
|
load_small_tools(19);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void minio_upload_menu_item(ActionEvent actionEvent) {
|
||||||
|
load_small_tools(20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
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 javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.stage.DirectoryChooser;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大文件上传
|
||||||
|
*
|
||||||
|
* @author zhangmeng
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2023年9月15日15:19:58
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class MinioUploadController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public TextField endpoint;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public TextField accessKey;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public TextField secretKey;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public TextField bucket;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public ImageView iv;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public Button file_choose;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public Button upload;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public TextField file_path;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void initialize() {
|
||||||
|
|
||||||
|
file_choose.setText(null);
|
||||||
|
ImageView iv = new ImageView(new Image(ImagePath.path(ImagePath.ImagePathType.IMAGE_FILE)));
|
||||||
|
iv.setPreserveRatio(true);
|
||||||
|
iv.setFitWidth(18);
|
||||||
|
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 -> {
|
||||||
|
|
||||||
|
if (endpoint.getText().length() == 0) {
|
||||||
|
AlertUtils.alert_warning("endpoint不能为空!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessKey.getText().length() == 0) {
|
||||||
|
AlertUtils.alert_warning("accessKey不能为空!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secretKey.getText().length() == 0) {
|
||||||
|
AlertUtils.alert_warning("secretKey不能为空!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bucket.getText().length() == 0) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
if (extension.equals("mp4") || extension.equals("avi")) {
|
||||||
|
videos_upload();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void videos_upload() {
|
||||||
|
File file = new File(file_path.getText());
|
||||||
|
MinioUtils.getInstance(endpoint.getText(), accessKey.getText(), secretKey.getText());
|
||||||
|
try {
|
||||||
|
MinioUtils.FileChunkReader filereader = new MinioUtils.FileChunkReader(file.toPath(), 1024 * 1024 * 10);
|
||||||
|
byte[] chunk;
|
||||||
|
int i = 0;
|
||||||
|
while ((chunk = filereader.readNextChunk()) != null) {
|
||||||
|
// process the chunk
|
||||||
|
String fileMd5 = DigestUtil.md5Hex(chunk);
|
||||||
|
//判断分块是否存在
|
||||||
|
if (!MinioUtils.checkChunk(fileMd5, i, bucket.getText())) {
|
||||||
|
//得到分块文件的目录路径
|
||||||
|
String chunkFileFolderPath = MinioUtils.getChunkFileFolderPath(fileMd5);
|
||||||
|
//得到分块文件的路径
|
||||||
|
String chunkFilePath = chunkFileFolderPath + i;
|
||||||
|
try {
|
||||||
|
//将文件存储至minIO
|
||||||
|
MinioUtils.addMediaFilesToMinIO(chunk, bucket.getText(), chunkFilePath, "application/octet-stream");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//合并分块
|
||||||
|
String fileExt = "";
|
||||||
|
String mergeFilePath = MinioUtils.getFilePathByMd5(filereader.getMd5(),fileExt);
|
||||||
|
|
||||||
|
try {
|
||||||
|
//上传文件到minIO
|
||||||
|
MinioUtils.addMediaFilesToMinIO(filereader.getFile().getAbsolutePath(), bucket.getText(), mergeFilePath);
|
||||||
|
log.debug("合并文件上传MinIO完成{}", filereader.getFile().getAbsolutePath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("合并文件时上传文件出错");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void images_upload() {
|
||||||
|
File file = new File(file_path.getText());
|
||||||
|
MinioUtils.getInstance(endpoint.getText(), accessKey.getText(), secretKey.getText());
|
||||||
|
try {
|
||||||
|
byte[] bytes = FileUtils.readFileToByteArray(file);
|
||||||
|
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);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void choose_file() {
|
||||||
|
Stage stage = (Stage) file_choose.getScene().getWindow();
|
||||||
|
FileChooser dc = new FileChooser();
|
||||||
|
dc.setTitle("文件选择");
|
||||||
|
dc.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("图片类型", "*.jpg", "*.png"));
|
||||||
|
File file = dc.showOpenDialog(stage);
|
||||||
|
if (file != null) {
|
||||||
|
String path = file.getAbsolutePath();
|
||||||
|
file_path.setText(path);
|
||||||
|
log.info("base64---file:{}", path);
|
||||||
|
iv.setImage(new Image(file.getPath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -86,6 +86,8 @@ public class SmallToolsController {
|
||||||
private AnchorPane file_edit;
|
private AnchorPane file_edit;
|
||||||
private AnchorPane layui_form_gen;
|
private AnchorPane layui_form_gen;
|
||||||
private AnchorPane log_console;
|
private AnchorPane log_console;
|
||||||
|
private AnchorPane editPlusCode;
|
||||||
|
private AnchorPane minioUpload;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ListView<ResourcesUtils.SmallTools> listView;
|
private ListView<ResourcesUtils.SmallTools> listView;
|
||||||
|
|
@ -431,10 +433,57 @@ public class SmallToolsController {
|
||||||
}
|
}
|
||||||
log_console(flag);
|
log_console(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newValue.getIndex() == 19) {
|
||||||
|
if (editPlusCode != null) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
editPlusCode(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue.getIndex() == 20) {
|
||||||
|
if (minioUpload != null) {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
minioUpload(flag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void minioUpload(boolean flag) {
|
||||||
|
|
||||||
|
//默认选择第一个
|
||||||
|
listView.getSelectionModel().select(20);
|
||||||
|
if (!flag) {
|
||||||
|
try {
|
||||||
|
root = FXMLLoader.load(ResourcesUtils.getResource("minio-upload"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
minioUpload = root;
|
||||||
|
} else {
|
||||||
|
root = minioUpload;
|
||||||
|
}
|
||||||
|
common_method();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void editPlusCode(boolean flag) {
|
||||||
|
//默认选择第一个
|
||||||
|
listView.getSelectionModel().select(19);
|
||||||
|
if (!flag) {
|
||||||
|
try {
|
||||||
|
root = FXMLLoader.load(ResourcesUtils.getResource("edit_plus_code"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
editPlusCode = root;
|
||||||
|
} else {
|
||||||
|
root = editPlusCode;
|
||||||
|
}
|
||||||
|
common_method();
|
||||||
|
}
|
||||||
|
|
||||||
private void log_console(boolean flag) {
|
private void log_console(boolean flag) {
|
||||||
//默认选择第一个
|
//默认选择第一个
|
||||||
listView.getSelectionModel().select(18);
|
listView.getSelectionModel().select(18);
|
||||||
|
|
@ -506,6 +555,8 @@ public class SmallToolsController {
|
||||||
case File_Edit -> new Image("image/编辑.png");
|
case File_Edit -> new Image("image/编辑.png");
|
||||||
case LayUI_Form_Gen -> new Image("image/layui.png");
|
case LayUI_Form_Gen -> new Image("image/layui.png");
|
||||||
case LogConsole -> new Image("image/layui.png");
|
case LogConsole -> new Image("image/layui.png");
|
||||||
|
case EditPlusCode -> new Image("image/layui.png");
|
||||||
|
case MinioUpload -> new Image("image/layui.png");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,43 @@ import java.nio.file.StandardOpenOption;
|
||||||
public class MinioUtils {
|
public class MinioUtils {
|
||||||
|
|
||||||
public static void getInstance(String endpoint, String accessKey, String secretKey) {
|
public static void getInstance(String endpoint, String accessKey, String secretKey) {
|
||||||
|
|
||||||
|
if (minioClient == null){
|
||||||
minioClient(endpoint, accessKey, secretKey);
|
minioClient(endpoint, accessKey, secretKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFilePathByMd5(String fileMd5, String fileExt) {
|
||||||
|
return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + fileMd5 + fileExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkChunk(String fileMd5, int chunkIndex,String bucket_name) {
|
||||||
|
//得到分块文件目录
|
||||||
|
String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
|
||||||
|
//得到分块文件的路径
|
||||||
|
String chunkFilePath = chunkFileFolderPath + chunkIndex;
|
||||||
|
|
||||||
|
//文件流
|
||||||
|
InputStream fileInputStream = null;
|
||||||
|
try {
|
||||||
|
fileInputStream = minioClient.getObject(
|
||||||
|
GetObjectArgs.builder()
|
||||||
|
.bucket(bucket_name)
|
||||||
|
.object(chunkFilePath)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
if (fileInputStream != null) {
|
||||||
|
//分块已存在
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
//分块未存在
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static class FileChunkReader implements AutoCloseable {
|
public static class FileChunkReader implements AutoCloseable {
|
||||||
|
|
||||||
private final FileChannel channel;
|
private final FileChannel channel;
|
||||||
|
|
@ -220,7 +254,7 @@ public class MinioUtils {
|
||||||
|
|
||||||
public static void test(String path){
|
public static void test(String path){
|
||||||
|
|
||||||
try (MinioUtils.FileChunkReader reader = new MinioUtils.FileChunkReader(Path.of(path), chunkSize);) { // 1MB chunk size
|
try (FileChunkReader reader = new FileChunkReader(Path.of(path), chunkSize);) { // 1MB chunk size
|
||||||
byte[] chunk;
|
byte[] chunk;
|
||||||
//扩展名
|
//扩展名
|
||||||
String extName = reader.getExtension();
|
String extName = reader.getExtension();
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,8 @@ public class ResourcesUtils {
|
||||||
File_Edit("文件编辑器", 16),
|
File_Edit("文件编辑器", 16),
|
||||||
LayUI_Form_Gen("layui-from 表单生成", 17),
|
LayUI_Form_Gen("layui-from 表单生成", 17),
|
||||||
LogConsole("日志输出", 18),
|
LogConsole("日志输出", 18),
|
||||||
|
EditPlusCode("edit-plus注册码", 19),
|
||||||
|
MinioUpload("minio-upload文件上传", 20),
|
||||||
;
|
;
|
||||||
|
|
||||||
SmallTools(String title, int index) {
|
SmallTools(String title, int index) {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@
|
||||||
<MenuItem mnemonicParsing="false" text="文件编辑器" onAction="#file_edit_menu_item"/>
|
<MenuItem mnemonicParsing="false" text="文件编辑器" onAction="#file_edit_menu_item"/>
|
||||||
<MenuItem mnemonicParsing="false" text="LayUI表单代码生成" onAction="#layui_form_gen_menu_item"/>
|
<MenuItem mnemonicParsing="false" text="LayUI表单代码生成" onAction="#layui_form_gen_menu_item"/>
|
||||||
<MenuItem mnemonicParsing="false" text="日志输出" onAction="#log_console_menu_item"/>
|
<MenuItem mnemonicParsing="false" text="日志输出" onAction="#log_console_menu_item"/>
|
||||||
|
<MenuItem mnemonicParsing="false" text="EditPlus注册码生成" onAction="#edit_plus_code_menu_item"/>
|
||||||
|
<MenuItem mnemonicParsing="false" text="minio文件上传" onAction="#minio_upload_menu_item"/>
|
||||||
</items>
|
</items>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.ProgressBar?>
|
||||||
|
<?import javafx.scene.control.TextField?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
|
||||||
|
<AnchorPane prefHeight="649.0" prefWidth="1200.0" style="-fx-background-color: 1px;" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zhangmeng.tools.controller.MinioUploadController">
|
||||||
|
<children>
|
||||||
|
<Label layoutX="265.0" layoutY="72.0" text="endpoint:" />
|
||||||
|
<TextField fx:id="endpoint" layoutX="344.0" layoutY="68.0" prefHeight="25.0" prefWidth="612.0" />
|
||||||
|
<TextField fx:id="accessKey" layoutX="344.0" layoutY="125.0" prefHeight="25.0" prefWidth="612.0" />
|
||||||
|
<TextField fx:id="secretKey" layoutX="344.0" layoutY="181.0" prefHeight="25.0" prefWidth="612.0" />
|
||||||
|
<Label layoutX="263.0" layoutY="129.0" text="accessKey:" />
|
||||||
|
<Label layoutX="264.0" layoutY="185.0" text="secretKey:" />
|
||||||
|
<Label layoutX="278.0" layoutY="242.0" text="bucket:" />
|
||||||
|
<TextField fx:id="bucket" layoutX="344.0" layoutY="238.0" prefHeight="25.0" prefWidth="612.0" />
|
||||||
|
<Label layoutX="284.0" layoutY="308.0" text="文件:" />
|
||||||
|
<AnchorPane layoutX="344.0" layoutY="317.0" prefHeight="153.0" prefWidth="227.0" style="-fx-border-color: gray;-fx-border-width: 1px">
|
||||||
|
<children>
|
||||||
|
<ImageView fx:id="iv" fitHeight="153.0" fitWidth="227.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
<Button fx:id="file_choose" layoutX="623.0" layoutY="382.0" mnemonicParsing="false" text="文件选择" />
|
||||||
|
<Button fx:id="upload" layoutX="752.0" layoutY="382.0" mnemonicParsing="false" text="上传" />
|
||||||
|
<ProgressBar layoutX="263.0" layoutY="539.0" prefHeight="7.0" prefWidth="746.0" progress="0.0" />
|
||||||
|
<Label layoutX="209.0" layoutY="534.0" text="进度:" />
|
||||||
|
<TextField fx:id="file_path" layoutX="623.0" layoutY="317.0" prefHeight="25.0" prefWidth="331.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
Loading…
Reference in New Issue