【问题标题】:Spring Boot + AWS S3: Unable to delete files in the bucketSpring Boot + AWS S3:无法删除存储桶中的文件
【发布时间】:2020-09-09 17:00:10
【问题描述】:

我是 AWS 新手,我尝试学习的第一个模块是用于文件存储的 S3。

上传工作正常,问题在于删除。因此,当我上传文件时,我将文件名称的字符串版本存储在 AWS 存储桶 mybucket 中,并将整个 URL 存储在 mysql 数据库中,如下所示 -> https://mybucket.s3.eu-west-2.amazonaws.com/what.png

删除的问题是,即使我在这种情况下将整个 URL https://mybucket.s3.eu-west-2.amazonaws.com/what.png 传递给 delete 方法,该方法也会成功执行每个步骤,告诉我文件已成功删除但是当我检查存储桶时,该文件仍然存在。我尝试在这里搜索类似的问题,但找不到可以帮助我理解问题所在的内容。这是代码

@Service
public class AmazonS3ClientServiceImpl {
    private String awsS3AudioBucket; //bucket name
    private AmazonS3 amazonS3; // s3 object which uploads file
    private static final Logger logger = LoggerFactory.getLogger(AmazonS3ClientServiceImpl.class);

    @Autowired
    public AmazonS3ClientServiceImpl(Region awsRegion, AWSCredentialsProvider awsCredentialsProvider, String awsS3AudioBucket) {
        this.amazonS3 = AmazonS3ClientBuilder.standard()
                .withCredentials(awsCredentialsProvider)
                .withRegion(awsRegion.getName()).build();
        this.awsS3AudioBucket = awsS3AudioBucket;
    }


    public String uploadFileToS3Bucket(MultipartFile multipartFile, boolean enablePublicReadAccess) {
        String uploadedfile = ""; // the file path which is on s3
        String fileName = multipartFile.getOriginalFilename();

        try {
            //creating the file in the server (temporarily)
            File file = new File(fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(multipartFile.getBytes());
            fos.close();

            PutObjectRequest putObjectRequest = new PutObjectRequest(this.awsS3AudioBucket, fileName, file);

            if (enablePublicReadAccess) {
                putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead);
            }
            this.amazonS3.putObject(putObjectRequest);
            uploadedfile = String.valueOf(this.amazonS3.getUrl(awsS3AudioBucket, fileName));
            System.out.println(this.amazonS3.getUrl(awsS3AudioBucket, fileName));
            System.out.println(uploadedfile);


            //removing the file created in the server
            file.delete();
        } catch (IOException | AmazonServiceException ex) {
            logger.error("error [" + ex.getMessage() + "] occurred while uploading [" + fileName + "] ");
        }
        return uploadedfile;
    }

    public void deleteFileFromS3Bucket(String fileName) {
        LOGGER.info("Deleting file with name= " + fileName);
        final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(this.awsS3AudioBucket, fileName);
        amazonS3.deleteObject(deleteObjectRequest);
        LOGGER.info("File deleted successfully");
    }

当我调用 deletemethod 时,我使用这个

@GetMapping("/dashboard/showposts/delete/{id}")
    public String deletePost(@PathVariable("id") Long id, Model model) {
        System.out.println("GOT HERE");
        //Retrieving Post image name
        Post post = postService.findBydId(id);
        String imageName = post.getImage();
        System.out.println(imageName);
        //Deleting image from S3 bucket
        amazonClient.deleteFileFromS3Bucket(imageName);
        //Deleting post from db
        postService.detelePost(id);
        String success = "Successfully deleted post with Id" + id;
        model.addAttribute("success", success);
        return "redirect:/admin/dashboard/showposts";
    }

任何帮助将不胜感激。

L.E 对于遇到相同问题并正在寻找快速答案的任何人。您只需将字符串图像名称传递给删除方法,而不是整个 URL。

【问题讨论】:

    标签: java spring amazon-web-services spring-boot amazon-s3


    【解决方案1】:

    您没有检查从amazonS3.deleteObject() 返回的响应以查看它是否真的成功。它可能正在返回失败状态。

    我猜测根本问题是您将完整的 URL 传递给 delete 方法,而不仅仅是 S3 中文件的路径。例如,使用此 URL:https://mybucket.s3.eu-west-2.amazonaws.com/what.png,S3 对象路径就是 what.png

    【讨论】:

    • 该方法返回 void(参见 V1 文档 here
    • 是的,我刚刚检查过,该方法返回 void。我确实可以通过传递它来检查what.png,但是当我像https://mybucket.s3.eu-west-2.amazonaws.com/what.png 这样将整个URL 保存在mysql db 列中并且当我调用getImage() 方法时它返回整个URL 时,我该怎么做呢?我将文件名与 URL 分开?
    • 这是一个不同的问题 - 如何解析出 URL 的各个部分。
    • 好的,我可以确认,当我将what.png 直接传递给它删除文件的方法时,我的问题仍然存在,因为我不知道如何将文件名与整个 URL 分开。这里有什么帮助吗?
    【解决方案2】:

    最简单的答案是使用URL 类。比如:

        URL url = null;
        try {
            url = new URL("https://mybucket.s3.eu-west-2.amazonaws.com/some/path/what.png");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    
        System.out.println( "file is \""+ url.getFile() + "\"" );
    

    输出将是“/some/path/what.png”。您可以删除用于键的第一个“/”字符。

    【讨论】:

      【解决方案3】:

      Aws S3 最终保持一致。您可以在 browser 中删除对象并 s3 列出该对象。所以删除需要几秒钟或更短的时间。

      请参考此链接

      【讨论】:

      • 我每次都等了1分钟以上,文件还在
      • 请检查该存储桶中是否启用了版本控制
      猜你喜欢
      • 1970-01-01
      • 2017-11-16
      • 2017-06-08
      • 2018-09-11
      • 2014-11-03
      • 2018-05-16
      • 1970-01-01
      • 2016-05-10
      • 2017-08-24
      相关资源
      最近更新 更多