在 TableView JavaFX 中为 ProgressIndicator 实现 S3 ProgressListener
Implementing S3 ProgressListener for ProgressIndicator in TableView JavaFX
我正在创建一个桌面软件,它会根据调度程序 he/she 的配置定期备份用户数据。它还具有手动上传文件的功能。我在 tablecell
中使用 ProgressIndicator
来指示上传状态。
这是问题所在:
如果我只上传一个文件并等待上传过程完成,ProgressIndicator
工作正常
但是如果我尝试在第一个文件完全上传之前上传另一个文件,那么 ProgressIndicator
将重置为 0% 并开始上传两个文件。
这是我的工作代码(我从 SO 上找到的不同示例编译而来)
Directory.java
import java.util.Objects;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.control.Button;
import javafx.util.Callback;
public class Directory {
private String filename;
private String fileLocation;
private String datetime;
private String filePath;
private String lastUpdated;
private String userdir_id;
private String userid;
private String directory;
private String device_id;
private String devicetype;
private DoubleProperty progressIndicator;
private String fileType;
Button addSchedular;
public Directory() {
}
public Directory(String fileName, String fileLocation, String date, String filePath, String fileType, double progressValue) {
this.filename = fileName;
this.fileLocation = fileLocation;
this.datetime = date;
this.filePath = filePath;
this.fileType = fileType;
this.progressIndicator = new SimpleDoubleProperty(progressValue);
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getFileLocation() {
return fileLocation;
}
public void setFileLocation(String fileLocation) {
this.fileLocation = fileLocation;
}
public String getDatetime() {
return datetime;
}
public void setDatetime(String datetime) {
this.datetime = datetime;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getUserdir_id() {
return userdir_id;
}
public void setUserdir_id(String userdir_id) {
this.userdir_id = userdir_id;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getDirectory() {
return directory;
}
public void setDirectory(String directory) {
this.directory = directory;
}
public String getDevice_id() {
return device_id;
}
public void setDevice_id(String device_id) {
this.device_id = device_id;
}
public String getDevicetype() {
return devicetype;
}
public void setDevicetype(String devicetype) {
this.devicetype = devicetype;
}
public double getProgressIndicator() {
return progressIndicator.get();
}
public DoubleProperty getProgressIndicatorProperty() {
return progressIndicator;
}
public void setProgressIndicator(double progressIndicator) {
this.progressIndicator = new SimpleDoubleProperty(progressIndicator);
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public Button getAddSchedular() {
return addSchedular;
}
public void setAddSchedular(Button addSchedular) {
this.addSchedular = addSchedular;
}
public static Callback<Directory, Observable[]> extractor() {
return (Directory d) -> new Observable[]{d.getProgressIndicatorProperty()};
}
@Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
Directory bean = (Directory) object;
if (this.filename.equals(bean.getFilename()) && this.fileLocation.equals(bean.getFileLocation())) {
result = true;
}
}
return result;
}
@Override
public int hashCode() {
int hash = 3;
hash = 31 * hash + Objects.hashCode(this.filename);
hash = 31 * hash + Objects.hashCode(this.fileLocation);
hash = 31 * hash + Objects.hashCode(this.filePath);
hash = 31 * hash + Objects.hashCode(this.userid);
hash = 31 * hash + Objects.hashCode(this.device_id);
hash = 31 * hash + Objects.hashCode(this.fileType);
return hash;
}
@Override
public String toString() {
return "DirectoryBean{" + "filename:" + filename + ", fileLocation:" + fileLocation + ", datetime:" + datetime + ", filePath:" + filePath + ", progressIndicator:" + progressIndicator + ", lastUpdated:" + lastUpdated + ", fileType:" + fileType + ", addSchedular:" + addSchedular + '}';
}
}
DirectoriesController.java(见onUploadFileAction()
方法)
import com.amazonaws.AmazonClientException;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressEventType;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.transfer.Upload;
import com.rayz.officebackup.Main;
import com.rayz.officebackup.models.Directory;
import com.rayz.officebackup.services.S3Service;
import com.rayz.officebackup.tablecells.ProgressIndicatorCell;
import com.rayz.officebackup.tablecells.SchedulerButtonCell;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* FXML Controller class
*
*
*/
public class DirectoriesController {
@FXML
AnchorPane directoryPane;
@FXML
TableView directoryTable;
@FXML
TableColumn<Directory, String> fileNameColumn;
@FXML
TableColumn<Directory, String> fileLocationColumn;
@FXML
TableColumn<Directory, String> dateColumn;
@FXML
TableColumn<Directory, Double> progressColumn;
@FXML
TableColumn<Directory, String> schedularColumn;
private static final Logger LOG = LoggerFactory.getLogger(DirectoriesController.class);
Upload upload = null;
Map<String, List<String>> dirMap = new HashMap<>();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String[] fileType = {"Uploaded", "Scheduled"};
public DirectoriesController() {
}
/**
* Initializes the controller class.
*
*/
@FXML
private void initialize() {
fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("filename"));
fileLocationColumn.setCellValueFactory(new PropertyValueFactory<>("fileLocation"));
dateColumn.setCellValueFactory(new PropertyValueFactory<>("datetime"));
progressColumn.setCellValueFactory(new PropertyValueFactory<>("progressIndicator"));
progressColumn.setCellFactory((TableColumn<Directory, Double> progressIndicatorColumn) -> new ProgressIndicatorCell());
schedularColumn.setCellValueFactory(new PropertyValueFactory<>("fileType"));
schedularColumn.setCellFactory((TableColumn<Directory, String> schedulerColumn) -> new SchedulerButtonCell(directoryTable));
//directoryList is an ObservableList which holds records for directoryTable
directoryTable.setItems(MainController.directoryList);
}
@FXML
private void onUploadFileAction(MouseEvent event) {
try {
S3Service s3Service = new S3Service();
FileChooser chooser = new FileChooser();
chooser.setTitle("Select File(s)");
List<File> files = chooser.showOpenMultipleDialog(Main.mainStage);
for (File file : files) {
Optional<Directory> optionalFile = MainController.directoryList.stream().filter(d -> {
return d.getFilename().equalsIgnoreCase(file.getName()) && d.getFilePath().equalsIgnoreCase(file.getAbsolutePath());
}).findFirst();
if (optionalFile.isPresent()) {
warnBox("Warning", "File Exists", "File " + file.getName() + " already exists!");
} else {
Directory directory = new Directory(file.getName(), file.getAbsolutePath(), dateFormat.format(new Date()), file.toPath().toString(), fileType[0], ProgressIndicator.INDETERMINATE_PROGRESS);
MainController.directoryList.add(0, directory);
directoryTable.setItems(MainController.directoryList);
updateDirMap(file.getName(), file.getAbsolutePath());
//<editor-fold>
ProgressListener progressListener = (ProgressEvent progressEvent) -> {
if (upload == null) {
return;
}
Platform.runLater(() -> {
directory.setProgressIndicator(upload.getProgress().getPercentTransferred() / 100.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
if (progressEvent.getEventType() == ProgressEventType.TRANSFER_COMPLETED_EVENT) {
Platform.runLater(() -> {
directory.setProgressIndicator(1.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
} else if (progressEvent.getEventType() == ProgressEventType.TRANSFER_FAILED_EVENT) {
try {
AmazonClientException ex = upload.waitForException();
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error Uploading File");
alert.setContentText("Unable to upload file to Amazon S3:" + ex.getMessage());
alert.showAndWait();
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
//</editor-fold>
upload = s3Service.uploadFile(file, file.length(), file.getName(), progressListener);
}
}
} catch (FileNotFoundException ex) {
LOG.error(ex.getMessage(), ex);
}
}
@FXML
private void onUploadDirectoryAction(MouseEvent event) {
DirectoryChooser directoryChooser = new DirectoryChooser();
File directory = directoryChooser.showDialog(((Node) event.getSource()).getScene().getWindow());
if (directory != null) {
Optional<Directory> optionalDirectory = MainController.directoryList.stream().filter(d -> {
return d.getFilename().equalsIgnoreCase(directory.getName()) && d.getFilePath().equalsIgnoreCase(directory.getAbsolutePath());
}).findFirst();
if (optionalDirectory.isPresent()) {
warnBox("Warning", "Directory Exists", "Directory " + directory.getName() + " already exists!");
} else {
MainController.directoryList.add(0, new Directory(directory.getName(), directory.getAbsolutePath(), null, directory.toPath().toString(), fileType[1], ProgressIndicator.INDETERMINATE_PROGRESS));
directoryTable.setItems(MainController.directoryList);
updateDirMap(directory.getName(), directory.getAbsolutePath());
}
}
}
@FXML
private void onDeleteAction(MouseEvent event) {
}
private void updateDirMap(String dirName, String filePath) {
if (dirMap.containsKey(dirName)) {
dirMap.get(dirName).add(filePath);
} else {
List<String> list = new ArrayList<>();
list.add(filePath);
dirMap.put(dirName, list);
}
}
private void alertBox(String infoMessage, String titleBar, String headerMessage) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(titleBar);
alert.setHeaderText(headerMessage);
alert.setContentText(infoMessage);
alert.showAndWait();
});
}
private void warnBox(String infoMessage, String titleBar, String headerMessage) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle(titleBar);
alert.setHeaderText(headerMessage);
alert.setContentText(infoMessage);
alert.showAndWait();
});
}
}
S3Service.java(见uploadFile()
方法)
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SDKGlobalConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressEventType;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsV2Request;
import com.amazonaws.services.s3.model.ListObjectsV2Result;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.transfer.MultipleFileDownload;
import com.amazonaws.services.s3.transfer.MultipleFileUpload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;
import com.rayz.officebackup.controllers.MainController;
import com.rayz.officebackup.models.Folder;
import com.rayz.officebackup.models.IFile;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.scene.control.Alert;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class S3Service {
private final String AWS_S3_BUCKET = "s3-bucket";
private String AWS_S3_BUCKET;
private static final String AWS_ACCESS_KEY = "access-key";
private static final String AWS_SECRET_KEY = "secret-key";
private final static AWSCredentials CREDENTIALS = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
private final static AmazonS3Client S3CLIENT = new AmazonS3Client(CREDENTIALS);
private static final String RESOURCE_CONTENT_TYPE = "text/xml";
private static final Logger LOG = LoggerFactory.getLogger(S3Service.class);
public MultipleFileUpload uploadDirectory(File directory, ProgressListener listener) throws FileNotFoundException {
System.setProperty(SDKGlobalConfiguration.ENABLE_IN_REGION_OPTIMIZED_MODE, "true");
TransferManager tm = new TransferManager(S3CLIENT);
MultipleFileUpload upload = tm.uploadDirectory(AWS_S3_BUCKET, directory.getName(), directory, true);
upload.addProgressListener(listener);
return upload;
}
public void downloadDirectory(String key, File downloadDirectory) {
System.setProperty(SDKGlobalConfiguration.ENABLE_IN_REGION_OPTIMIZED_MODE, "true");
TransferManager tm = TransferManagerBuilder.standard().withS3Client(S3CLIENT).build();
MultipleFileDownload download = tm.downloadDirectory(AWS_S3_BUCKET, key, downloadDirectory);
}
public Upload uploadFile(File file, long fileSize, String filePath, ProgressListener listener) throws FileNotFoundException {
System.setProperty(SDKGlobalConfiguration.ENABLE_IN_REGION_OPTIMIZED_MODE, "true");
ObjectMetadata objectMetaData = new ObjectMetadata();
objectMetaData.setContentLength(fileSize);
objectMetaData.setContentType(RESOURCE_CONTENT_TYPE);
objectMetaData.setCacheControl("public");
PutObjectRequest putObjectRequest = new PutObjectRequest(AWS_S3_BUCKET, filePath, file)
.withCannedAcl(CannedAccessControlList.PublicRead)
.withGeneralProgressListener(listener);
TransferManager tm = new TransferManager(S3CLIENT);
return tm.upload(putObjectRequest);
}
}
让我知道哪里做错了
正如您所说,我认为您的错误在于 onUploadFileAction()
方法。
如果我 运行 通过 progresListener
,我注意到您在其中使用了变量 upload
,然后在创建此 listener
之后立即设置upload
变量。因此,如果您背靠背上传两个文件,每当第一个文件抛出 ProgressEvent
时,它将使用第二个文件新设置的 upload
变量更新指标,假设事件不是 TRANSFER_COMPLETED_EVENT
然后会显示第二个文件的上传进度。
为了解决这个问题,将 upload
移动到方法中并使其成为 ObjectProperty<Upload>
以便您可以在 lambda 中使用它。
希望这对您有所帮助。
ObjectProperty<Upload> upload = new SimpleObjectProperty();
ProgressListener progressListener = (ProgressEvent progressEvent) -> {
if (upload.get() == null) {
return;
}
Platform.runLater(() -> {
directory.setProgressIndicator(upload.get().getProgress().getPercentTransferred() / 100.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
if (progressEvent.getEventType() == ProgressEventType.TRANSFER_COMPLETED_EVENT) {
Platform.runLater(() -> {
directory.setProgressIndicator(1.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
} else if (progressEvent.getEventType() == ProgressEventType.TRANSFER_FAILED_EVENT) {
try {
AmazonClientException ex = upload.get().waitForException();
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error Uploading File");
alert.setContentText("Unable to upload file to Amazon S3:" + ex.getMessage());
alert.showAndWait();
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
//</editor-fold>
upload.set(s3Service.uploadFile(file, file.length(), file.getName(), progressListener));
我正在创建一个桌面软件,它会根据调度程序 he/she 的配置定期备份用户数据。它还具有手动上传文件的功能。我在 tablecell
中使用 ProgressIndicator
来指示上传状态。
这是问题所在:
如果我只上传一个文件并等待上传过程完成,ProgressIndicator
工作正常
ProgressIndicator
将重置为 0% 并开始上传两个文件。
这是我的工作代码(我从 SO 上找到的不同示例编译而来)
Directory.java
import java.util.Objects;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.control.Button;
import javafx.util.Callback;
public class Directory {
private String filename;
private String fileLocation;
private String datetime;
private String filePath;
private String lastUpdated;
private String userdir_id;
private String userid;
private String directory;
private String device_id;
private String devicetype;
private DoubleProperty progressIndicator;
private String fileType;
Button addSchedular;
public Directory() {
}
public Directory(String fileName, String fileLocation, String date, String filePath, String fileType, double progressValue) {
this.filename = fileName;
this.fileLocation = fileLocation;
this.datetime = date;
this.filePath = filePath;
this.fileType = fileType;
this.progressIndicator = new SimpleDoubleProperty(progressValue);
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getFileLocation() {
return fileLocation;
}
public void setFileLocation(String fileLocation) {
this.fileLocation = fileLocation;
}
public String getDatetime() {
return datetime;
}
public void setDatetime(String datetime) {
this.datetime = datetime;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getUserdir_id() {
return userdir_id;
}
public void setUserdir_id(String userdir_id) {
this.userdir_id = userdir_id;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getDirectory() {
return directory;
}
public void setDirectory(String directory) {
this.directory = directory;
}
public String getDevice_id() {
return device_id;
}
public void setDevice_id(String device_id) {
this.device_id = device_id;
}
public String getDevicetype() {
return devicetype;
}
public void setDevicetype(String devicetype) {
this.devicetype = devicetype;
}
public double getProgressIndicator() {
return progressIndicator.get();
}
public DoubleProperty getProgressIndicatorProperty() {
return progressIndicator;
}
public void setProgressIndicator(double progressIndicator) {
this.progressIndicator = new SimpleDoubleProperty(progressIndicator);
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public Button getAddSchedular() {
return addSchedular;
}
public void setAddSchedular(Button addSchedular) {
this.addSchedular = addSchedular;
}
public static Callback<Directory, Observable[]> extractor() {
return (Directory d) -> new Observable[]{d.getProgressIndicatorProperty()};
}
@Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
Directory bean = (Directory) object;
if (this.filename.equals(bean.getFilename()) && this.fileLocation.equals(bean.getFileLocation())) {
result = true;
}
}
return result;
}
@Override
public int hashCode() {
int hash = 3;
hash = 31 * hash + Objects.hashCode(this.filename);
hash = 31 * hash + Objects.hashCode(this.fileLocation);
hash = 31 * hash + Objects.hashCode(this.filePath);
hash = 31 * hash + Objects.hashCode(this.userid);
hash = 31 * hash + Objects.hashCode(this.device_id);
hash = 31 * hash + Objects.hashCode(this.fileType);
return hash;
}
@Override
public String toString() {
return "DirectoryBean{" + "filename:" + filename + ", fileLocation:" + fileLocation + ", datetime:" + datetime + ", filePath:" + filePath + ", progressIndicator:" + progressIndicator + ", lastUpdated:" + lastUpdated + ", fileType:" + fileType + ", addSchedular:" + addSchedular + '}';
}
}
DirectoriesController.java(见onUploadFileAction()
方法)
import com.amazonaws.AmazonClientException;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressEventType;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.transfer.Upload;
import com.rayz.officebackup.Main;
import com.rayz.officebackup.models.Directory;
import com.rayz.officebackup.services.S3Service;
import com.rayz.officebackup.tablecells.ProgressIndicatorCell;
import com.rayz.officebackup.tablecells.SchedulerButtonCell;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* FXML Controller class
*
*
*/
public class DirectoriesController {
@FXML
AnchorPane directoryPane;
@FXML
TableView directoryTable;
@FXML
TableColumn<Directory, String> fileNameColumn;
@FXML
TableColumn<Directory, String> fileLocationColumn;
@FXML
TableColumn<Directory, String> dateColumn;
@FXML
TableColumn<Directory, Double> progressColumn;
@FXML
TableColumn<Directory, String> schedularColumn;
private static final Logger LOG = LoggerFactory.getLogger(DirectoriesController.class);
Upload upload = null;
Map<String, List<String>> dirMap = new HashMap<>();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String[] fileType = {"Uploaded", "Scheduled"};
public DirectoriesController() {
}
/**
* Initializes the controller class.
*
*/
@FXML
private void initialize() {
fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("filename"));
fileLocationColumn.setCellValueFactory(new PropertyValueFactory<>("fileLocation"));
dateColumn.setCellValueFactory(new PropertyValueFactory<>("datetime"));
progressColumn.setCellValueFactory(new PropertyValueFactory<>("progressIndicator"));
progressColumn.setCellFactory((TableColumn<Directory, Double> progressIndicatorColumn) -> new ProgressIndicatorCell());
schedularColumn.setCellValueFactory(new PropertyValueFactory<>("fileType"));
schedularColumn.setCellFactory((TableColumn<Directory, String> schedulerColumn) -> new SchedulerButtonCell(directoryTable));
//directoryList is an ObservableList which holds records for directoryTable
directoryTable.setItems(MainController.directoryList);
}
@FXML
private void onUploadFileAction(MouseEvent event) {
try {
S3Service s3Service = new S3Service();
FileChooser chooser = new FileChooser();
chooser.setTitle("Select File(s)");
List<File> files = chooser.showOpenMultipleDialog(Main.mainStage);
for (File file : files) {
Optional<Directory> optionalFile = MainController.directoryList.stream().filter(d -> {
return d.getFilename().equalsIgnoreCase(file.getName()) && d.getFilePath().equalsIgnoreCase(file.getAbsolutePath());
}).findFirst();
if (optionalFile.isPresent()) {
warnBox("Warning", "File Exists", "File " + file.getName() + " already exists!");
} else {
Directory directory = new Directory(file.getName(), file.getAbsolutePath(), dateFormat.format(new Date()), file.toPath().toString(), fileType[0], ProgressIndicator.INDETERMINATE_PROGRESS);
MainController.directoryList.add(0, directory);
directoryTable.setItems(MainController.directoryList);
updateDirMap(file.getName(), file.getAbsolutePath());
//<editor-fold>
ProgressListener progressListener = (ProgressEvent progressEvent) -> {
if (upload == null) {
return;
}
Platform.runLater(() -> {
directory.setProgressIndicator(upload.getProgress().getPercentTransferred() / 100.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
if (progressEvent.getEventType() == ProgressEventType.TRANSFER_COMPLETED_EVENT) {
Platform.runLater(() -> {
directory.setProgressIndicator(1.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
} else if (progressEvent.getEventType() == ProgressEventType.TRANSFER_FAILED_EVENT) {
try {
AmazonClientException ex = upload.waitForException();
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error Uploading File");
alert.setContentText("Unable to upload file to Amazon S3:" + ex.getMessage());
alert.showAndWait();
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
//</editor-fold>
upload = s3Service.uploadFile(file, file.length(), file.getName(), progressListener);
}
}
} catch (FileNotFoundException ex) {
LOG.error(ex.getMessage(), ex);
}
}
@FXML
private void onUploadDirectoryAction(MouseEvent event) {
DirectoryChooser directoryChooser = new DirectoryChooser();
File directory = directoryChooser.showDialog(((Node) event.getSource()).getScene().getWindow());
if (directory != null) {
Optional<Directory> optionalDirectory = MainController.directoryList.stream().filter(d -> {
return d.getFilename().equalsIgnoreCase(directory.getName()) && d.getFilePath().equalsIgnoreCase(directory.getAbsolutePath());
}).findFirst();
if (optionalDirectory.isPresent()) {
warnBox("Warning", "Directory Exists", "Directory " + directory.getName() + " already exists!");
} else {
MainController.directoryList.add(0, new Directory(directory.getName(), directory.getAbsolutePath(), null, directory.toPath().toString(), fileType[1], ProgressIndicator.INDETERMINATE_PROGRESS));
directoryTable.setItems(MainController.directoryList);
updateDirMap(directory.getName(), directory.getAbsolutePath());
}
}
}
@FXML
private void onDeleteAction(MouseEvent event) {
}
private void updateDirMap(String dirName, String filePath) {
if (dirMap.containsKey(dirName)) {
dirMap.get(dirName).add(filePath);
} else {
List<String> list = new ArrayList<>();
list.add(filePath);
dirMap.put(dirName, list);
}
}
private void alertBox(String infoMessage, String titleBar, String headerMessage) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(titleBar);
alert.setHeaderText(headerMessage);
alert.setContentText(infoMessage);
alert.showAndWait();
});
}
private void warnBox(String infoMessage, String titleBar, String headerMessage) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle(titleBar);
alert.setHeaderText(headerMessage);
alert.setContentText(infoMessage);
alert.showAndWait();
});
}
}
S3Service.java(见uploadFile()
方法)
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SDKGlobalConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressEventType;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsV2Request;
import com.amazonaws.services.s3.model.ListObjectsV2Result;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.transfer.MultipleFileDownload;
import com.amazonaws.services.s3.transfer.MultipleFileUpload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;
import com.rayz.officebackup.controllers.MainController;
import com.rayz.officebackup.models.Folder;
import com.rayz.officebackup.models.IFile;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.scene.control.Alert;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class S3Service {
private final String AWS_S3_BUCKET = "s3-bucket";
private String AWS_S3_BUCKET;
private static final String AWS_ACCESS_KEY = "access-key";
private static final String AWS_SECRET_KEY = "secret-key";
private final static AWSCredentials CREDENTIALS = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
private final static AmazonS3Client S3CLIENT = new AmazonS3Client(CREDENTIALS);
private static final String RESOURCE_CONTENT_TYPE = "text/xml";
private static final Logger LOG = LoggerFactory.getLogger(S3Service.class);
public MultipleFileUpload uploadDirectory(File directory, ProgressListener listener) throws FileNotFoundException {
System.setProperty(SDKGlobalConfiguration.ENABLE_IN_REGION_OPTIMIZED_MODE, "true");
TransferManager tm = new TransferManager(S3CLIENT);
MultipleFileUpload upload = tm.uploadDirectory(AWS_S3_BUCKET, directory.getName(), directory, true);
upload.addProgressListener(listener);
return upload;
}
public void downloadDirectory(String key, File downloadDirectory) {
System.setProperty(SDKGlobalConfiguration.ENABLE_IN_REGION_OPTIMIZED_MODE, "true");
TransferManager tm = TransferManagerBuilder.standard().withS3Client(S3CLIENT).build();
MultipleFileDownload download = tm.downloadDirectory(AWS_S3_BUCKET, key, downloadDirectory);
}
public Upload uploadFile(File file, long fileSize, String filePath, ProgressListener listener) throws FileNotFoundException {
System.setProperty(SDKGlobalConfiguration.ENABLE_IN_REGION_OPTIMIZED_MODE, "true");
ObjectMetadata objectMetaData = new ObjectMetadata();
objectMetaData.setContentLength(fileSize);
objectMetaData.setContentType(RESOURCE_CONTENT_TYPE);
objectMetaData.setCacheControl("public");
PutObjectRequest putObjectRequest = new PutObjectRequest(AWS_S3_BUCKET, filePath, file)
.withCannedAcl(CannedAccessControlList.PublicRead)
.withGeneralProgressListener(listener);
TransferManager tm = new TransferManager(S3CLIENT);
return tm.upload(putObjectRequest);
}
}
让我知道哪里做错了
正如您所说,我认为您的错误在于 onUploadFileAction()
方法。
如果我 运行 通过 progresListener
,我注意到您在其中使用了变量 upload
,然后在创建此 listener
之后立即设置upload
变量。因此,如果您背靠背上传两个文件,每当第一个文件抛出 ProgressEvent
时,它将使用第二个文件新设置的 upload
变量更新指标,假设事件不是 TRANSFER_COMPLETED_EVENT
然后会显示第二个文件的上传进度。
为了解决这个问题,将 upload
移动到方法中并使其成为 ObjectProperty<Upload>
以便您可以在 lambda 中使用它。
希望这对您有所帮助。
ObjectProperty<Upload> upload = new SimpleObjectProperty();
ProgressListener progressListener = (ProgressEvent progressEvent) -> {
if (upload.get() == null) {
return;
}
Platform.runLater(() -> {
directory.setProgressIndicator(upload.get().getProgress().getPercentTransferred() / 100.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
if (progressEvent.getEventType() == ProgressEventType.TRANSFER_COMPLETED_EVENT) {
Platform.runLater(() -> {
directory.setProgressIndicator(1.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory), directory);
});
} else if (progressEvent.getEventType() == ProgressEventType.TRANSFER_FAILED_EVENT) {
try {
AmazonClientException ex = upload.get().waitForException();
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error Uploading File");
alert.setContentText("Unable to upload file to Amazon S3:" + ex.getMessage());
alert.showAndWait();
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
//</editor-fold>
upload.set(s3Service.uploadFile(file, file.length(), file.getName(), progressListener));