简体   繁体   English

AWS S3 上传文件名不匹配

[英]AWS S3 upload file name mismatch

I am able to upload multiple files to s3 bucket at once.我可以一次将多个文件上传到 s3 存储桶。 However there is a mismatch in the file name the one I provided and uploaded file.但是,文件名与我提供和上传的文件不匹配。 I am interested in file name as I need to generate cloud front signed url based on that.我对文件名感兴趣,因为我需要基于此生成云前端签名的 url。

File generation code文件生成代码

final String fileName = System.currentTimeMillis() + pictureData.getFileName();
final File file = new File(fileName); //fileName is -> 1594125913522_image1.png
writeByteArrayToFile(img, file);

AWS file upload code AWS 文件上传代码

public void uploadMultipleFiles(final List<File> files) {

        final TransferManager transferManager = TransferManagerBuilder.standard().withS3Client(amazonS3).build();
        try {
            final MultipleFileUpload xfer = transferManager.uploadFileList(bucketName, null, new File("."), files);
            xfer.waitForCompletion();
        } catch (InterruptedException exception) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("InterruptedException occurred=>" + exception);
            }
        } catch (AmazonServiceException exception) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("AmazonServiceException occurred =>" + exception);
            }
            throw exception;
        }
    }

Uploaded file name is 94125913522_image1.png .上传的文件名为94125913522_image1.png As you can see first two characters disappeared.如您所见,前两个字符消失了。 What am I missing here.我在这里想念什么。 I am not able to figure out.我无法弄清楚。 Kindly advice.好心劝告。

private static void writeByteArrayToFile(final byte[] byteArray, final File file) {
        try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get(file.getName())))) {
            outputStream.write(byteArray);
        } catch (IOException exception) {
            throw new FileIllegalStateException("Error while writing image to file", exception);
        }
    }

The reason of the problem问题的原因

You lose the first two charecters of the file names because of the third argument of this method:由于此方法的第三个参数,您会丢失文件名的前两个字符:

transferManager.uploadFileList(bucketName, null, new File("."), files);

What happens in this case在这种情况下会发生什么

So, what is the third argument:那么,第三个论点是什么:

/**
...
* @param directory
* The common parent directory of files to upload. The keys
* of the files in the list of files are constructed relative to
* this directory and the virtualDirectoryKeyPrefix.
...
*/
public MultipleFileUpload uploadFileList(... , File directory, ...){...}

And how will it be used:以及如何使用:

...
int startingPosition = directory.getAbsolutePath().length();
            if (!(directory.getAbsolutePath().endsWith(File.separator)))
                startingPosition++;
...
String key = f.getAbsolutePath().substring(startingPosition)...

Thus, the directory variable is used to define a starting index to trim file paths to get file keys.因此,目录变量用于定义起始索引以修剪文件路径以获取文件密钥。

When you pass new File(".") as a directory, the parent directory for your files will be {your_path}.当您将new File(".")作为目录传递时,文件的父目录将是{your_path}。

But this is a directory, and you need to work with files inside it.但这是一个目录,您需要处理其中的文件。 So the common part, retrieved from your directory file, is {your_path}./因此,从您的目录文件中检索的公共部分是{your_path}./

That is 2 symbols more than you actually need.这比您实际需要的符号多 2 个。 And for this reason this method trims the 2 extra characters - an extra shift of two characters when trimming the file path.出于这个原因,此方法会修剪 2 个额外字符 - 修剪文件路径时额外移动两个字符。

The solution解决方案

If you only need to work with the current directory, you can pass the current directory as follows:如果只需要处理当前目录,可以通过如下方式传递当前目录:

MultipleFileUpload upload = transferManager.uploadFileList(bucketName, "", 
                            System.getProperty("user.dir"), files);

But if you start working with external sources, it won't work.但是如果你开始使用外部资源,它就行不通了。 So you can use this code, which creates one MultipleFileUpload per group of files from one directory.因此,您可以使用此代码,它从一个目录中为每组文件创建一个 MultipleFileUpload。


private final String PATH_SEPARATOR = File.separator;
private String bucketName;
private TransferManager transferManager;

public void uploadMultipleFiles(String prefix, List<File> filesToUpload){
    Map<File, List<File>> multipleUploadArguments = 
                  getMultipleUploadArguments(filesToUpload);
    for (Map.Entry<File, List<File>> multipleUploadArgument:
                                      multipleUploadArguments.entrySet()){
        try{
            MultipleFileUpload upload = transferManager.uploadFileList(
                    bucketName, prefix,
                    multipleUploadArgument.getKey(),
                    multipleUploadArgument.getValue()
            );
            upload.waitForCompletion();
        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }
    }
}

private Map<File, List<File>> getMultipleUploadArguments(List<File> filesToUpload){
    return filesToUpload.stream()
            .collect(Collectors.groupingBy(this::getDirectoryPathForFile));
}

private File getDirectoryPathForFile(File file){
    String filePath = file.getAbsolutePath();
    String directoryPath = filePath.substring(0, filePath.lastIndexOf(PATH_SEPARATOR));
    return new File(directoryPath);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM