Spring Boot + AWS S3:无法删除存储桶中的文件

huangapple go评论74阅读模式
英文:

Spring Boot + AWS S3: Unable to delete files in the bucket

问题

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

上传工作正常,问题出在删除上。所以当我上传一个文件时,我会将文件的字符串版本的名称存储在名为mybucket的AWS存储桶中,将整个URL存储在mysql数据库中,就像这样:
-> https://mybucket.s3.eu-west-2.amazonaws.com/what.png

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

@Service
public class AmazonS3ClientServiceImpl {
    // ...(代码被截断,以下为部分代码)
    
    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");
    }
}

调用删除方法时,我使用以下代码:

@GetMapping("/dashboard/showposts/delete/{id}")
public String deletePost(@PathVariable("id") Long id, Model model) {
    System.out.println("GOT HERE");
    //检索帖子图像名称
    Post post = postService.findBydId(id);
    String imageName = post.getImage();
    System.out.println(imageName);
    //从S3存储桶中删除图像
    amazonClient.deleteFileFromS3Bucket(imageName);
    //从数据库中删除帖子
    postService.detelePost(id);
    String success = "Successfully deleted post with Id " + id;
    model.addAttribute("success", success);
    return "redirect:/admin/dashboard/showposts";
}

任何帮助将不胜感激。

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

英文:

i am new to AWS, and my first module i try to learn is S3 for file storage.

Uploading works fine, the problem is with deleting.So when i upload a file i store the string version of the name of the file in AWS bucket mybucket and the whole URL in mysql database like this
-> https://mybucket.s3.eu-west-2.amazonaws.com/what.png

The problem with deleting is that even if i pass the whole URL in this case https://mybucket.s3.eu-west-2.amazonaws.com/what.png to the delete method, the method goes to each steps successfully, telling me that the file has been succesfully deleted but when i check the bucket, the file is still there.I have tried searching around here for a similar issue, but couldn't find something that could help me understand what the problem is.here is the code

@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");
    }

and when i call the deletemethod i use this

@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";
    }

Any help would be greatly appreciated.

L.E For anyone having the same issue and searching for a quick answer.You have to pass only the string image name to the delete method not the whole URL.

答案1

得分: 1

你没有检查来自 amazonS3.deleteObject() 的响应,以查看它是否实际上成功了。很可能它正在返回一个失败状态。

我猜想根本问题是您正在将完整 URL 传递给删除方法,而不仅仅是 S3 内文件的路径。例如,对于此 URL:https://mybucket.s3.eu-west-2.amazonaws.com/what.png,S3 对象路径只是 what.png

英文:

You aren't checking the response returned from amazonS3.deleteObject() to see if it was actually successful or not. It is probably returning a failure status.

I'm guessing the root issue is that you are passing the full URL to the delete method, instead of just the path to the file within S3. For example with this URL: https://mybucket.s3.eu-west-2.amazonaws.com/what.png the S3 object path is simply what.png.

答案2

得分: 1

最简单的方法是使用<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html">URL</a>类。大致如下:

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( "文件为 &quot;"+ url.getFile() + "&quot;" );

输出将会是 "/some/path/what.png"。您可以去除第一个 "/" 字符以用作键名。

英文:

The simplest answer is to use the <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html">URL</a> class. Something like:

    URL url = null;
    try {
        url = new URL(&quot;https://mybucket.s3.eu-west-2.amazonaws.com/some/path/what.png&quot;);
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }

    System.out.println( &quot;file is \&quot;&quot;+ url.getFile() + &quot;\&quot;&quot; );

output would be "/some/path/what.png". You can remove the first "/" character to use for the key.

答案3

得分: 0

AWS S3是最终一致性的。您可能会删除对象并在S3中的浏览器中列出该对象。因此,删除操作可能需要几秒钟或更短的时间。

请参考此链接:

英文:

Aws S3 is eventual consistent. You might delete object and s3 list that object in browser . So it take few seconds or less to delete .

Please refer this link

huangapple
  • 本文由 发表于 2020年9月10日 01:00:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63816252.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定