在TableView JavaFX中实现ProgressIndicator的S3 ProgressListener

在TableView JavaFX中实现ProgressIndicator的S3 ProgressListener,java,javafx,amazon-s3,aws-sdk,progress-indicator,Java,Javafx,Amazon S3,Aws Sdk,Progress Indicator,我正在创建一个桌面软件,根据用户配置的调度程序定期备份用户数据。它还具有手动上传文件的功能。我在表格单元格中使用ProgressIndicator来指示上载状态 问题是: 如果我只上传一个文件并等待上传过程完成,ProgressIndicator工作正常 但是,如果在第一个文件完全上载之前尝试上载另一个文件,则ProgressIndicator将重置为0%,并开始上载这两个文件。 这是我的工作代码(我根据SO上的不同示例编译) Directory.java import java.util.O

我正在创建一个桌面软件,根据用户配置的调度程序定期备份用户数据。它还具有手动上传文件的功能。我在
表格单元格中使用
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 + '}';
    }
}  
S3Service.java(请参阅
uploadFile()
方法)


让我知道我哪里做错了

正如您所说,我相信您的错误在于
onUploadFileAction()
方法

如果我运行
progresstener
,我注意到您在其中使用了变量
upload
,然后在创建了
listener
之后,立即设置
upload
变量。因此,如果您背靠背上载两个文件,每当对第一个文件抛出
ProgressEvent
时,它将使用第二个文件新设置的
upload
变量更新指示器,假设事件不是
TRANSFER\u COMPLETED\u event
,则它将显示第二个文件上载进度

为了解决这个问题,将
upload
移动到方法中,并将其设置为
ObjectProperty
,以便可以在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));
ObjectProperty upload=new SimpleObjectProperty();
ProgressListener=(ProgressEvent ProgressEvent)->{
if(upload.get()==null){
返回;
}
Platform.runLater(()->{
目录.setProgressIndicator(upload.get().getProgress().getPercentTransfer()/100.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory),directory);
});
if(progressEvent.getEventType()==ProgressEventType.TRANSFER\u COMPLETED\u事件){
Platform.runLater(()->{
目录.setProgressIndicator(1.0d);
MainController.directoryList.set(MainController.directoryList.indexOf(directory),directory);
});
}else if(progressEvent.getEventType()==ProgressEventType.TRANSFER\u FAILED\u事件){
试一试{
AmazonClientException ex=upload.get().waitForException();
Platform.runLater(()->{
警报=新警报(Alert.AlertType.ERROR);
alert.setTitle(“上传文件时出错”);
alert.setContentText(“无法将文件上载到AmazonS3:+ex.getMessage());
alert.showAndWait();
});
}捕捉(中断异常e){
Thread.currentThread().interrupt();
}
}
};
//
set(s3Service.uploadFile(file,file.length(),file.getName(),progressListener));

因此,根据您发布的代码,任何建议都可以避免使用
ProgressListener
,看起来
upload
可能是一个局部变量,在
onUploadFileAction()中创建。我看不到它在其他任何地方被使用。我的建议是移动
Upload-Upload=null
就在
progressListener
@Jerk的正上方,我尝试过这样做……但是
upload
必须是
final
有效final
,如果我必须在事件处理程序中使用它的话。至少这是
NetBeans
通过执行
ObjectProperty upload=new SimpleObjectProperty()告诉meTrick的
然后使用相应的
.get()
.set()
查看我的更新答案,特别是所有的
upload.get()
,尤其是
upload.set()
。我相信这就是你所缺少的。
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);
    }
}  
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));