首页  >  文章  >  Java  >  使用 Spring Boot 和 iDrive E3 存储 UGC 应用程序的图像

使用 Spring Boot 和 iDrive E3 存储 UGC 应用程序的图像

DDD
DDD原创
2024-10-14 06:11:29898浏览

世界你好!

这是关于我在 Makers 构建社交网络克隆的经历的第二篇文章。第一篇文章的链接 - https://dev.to/olnov/working-with-http-requests-in-spring-boot-5el0。 当前的一个专门用于存储用户个人资料的图像。

步骤#1。计划。

作为 MVP 的一部分,我们决定实现以下用户故事:

作为用户,

我想更新我的个人资料以包含我的照片,

以便其他用户可以轻松在应用程序中找到我

我们还就非功能性需求达成了一致。

  • 图像文件仅限 PNG 或 JPG。
  • 文件大小不得超过 1 MB。

步骤#2。分析和设计。

我们提出了不同的图像存储位置选项 - 远程服务器文件夹、数据库和对象存储。尽管我们的应用程序负载不高,但我们决定使用 S3 作为分布式系统最合适的解决方案。 (P.S. 和我已经从之前的项目订阅了 iDrive e2)。

在数据库中,只有 iDrive 存储的公共 URL 的链接。

这是数据库图:

Storing images for your UGC app using Spring Boot and iDrive E3

高级应用图:

Storing images for your UGC app using Spring Boot and iDrive E3

步骤#3。构建。

后端部分需要完成以下内容:

  • 将 AWS SDK 添加到项目中。
  • 实现图像服务以与外部集成配合使用。
  • 实现图像控制器,使用图像服务将图像放入存储桶中,并将相应的记录保存在数据库中。

在 pom.xml 中我添加了以下内容:

       <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
            <version>2.28.18</version>
        </dependency>

图像服务类:

package com.makersacademy.acebook.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

import java.io.InputStream;
import java.net.URI;
import java.util.UUID;

@Service
public class ImageService {

    private final S3Client s3Client;

    @Value("${idrive.e2.bucket-name}")
    private String bucketName;

    @Value("${idrive.e2.endpoint}")
    private String endpoint;

    @Value("${idrive.e2.public_endpoint}")
    private String public_endpoint;

    public ImageService(@Value("${idrive.e2.access-key}") String accessKey,
                        @Value("${idrive.e2.secret-key}") String secretKey,
                        @Value("${idrive.e2.endpoint}") String endpoint) {
        AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
        this.s3Client = S3Client.builder()
                .credentialsProvider(StaticCredentialsProvider.create(credentials))
                .endpointOverride(URI.create(endpoint))
                .region(Region.AWS_GLOBAL) // I dind't see exact instructions from iDrive, so I set this parameter to AWS_GLOBAL
                .build();
    }

    public String uploadImage(InputStream imageStream, long contentLength, String contentType) {
        String key = "media/" + UUID.randomUUID();

        PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                .bucket(bucketName)
                .key(key)
                .contentType(contentType)
                .contentLength(contentLength) // Specify the content length
                .build();

        s3Client.putObject(putObjectRequest, software.amazon.awssdk.core.sync.RequestBody.fromInputStream(imageStream, contentLength));

        // Return the image URL
        return public_endpoint + "/" + bucketName + "/" + key;
    }
}

Idrive 连接变量存储在 application.properties 文件中:

#S3 storage settings
idrive.e2.access-key=${E2_ACCESS_KEY}
idrive.e2.secret-key=${E2_SECRET_KEY}
idrive.e2.endpoint=${E2_ENDPOINT}
idrive.e2.bucket-name=${E2_BUCKET_NAME}
idrive.e2.public_endpoint=${E2_PUBLIC_ENDPOINT}

好的,现在 ImageController 类:

package com.makersacademy.acebook.controller;

import com.makersacademy.acebook.model.Post;
import com.makersacademy.acebook.repository.PostRepository;
import com.makersacademy.acebook.service.ImageService;
import com.makersacademy.acebook.model.User;
import com.makersacademy.acebook.repository.UserRepository;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.RedirectView;

import java.io.IOException;

@Controller
public class ImageController {

    @Autowired
    private ImageService imageService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PostRepository postRepository;

    @PostMapping("/upload/{userId}")
    public RedirectView uploadImage(@PathVariable Long userId, @RequestParam("file") MultipartFile file) {
        try {
            // Check if the user exists
            User user = userRepository.findById(userId).orElseThrow(()->new RuntimeException("User not found"));

            // Upload image to IDrive e2 and get image URL
            String imageUrl = imageService.uploadImage(file.getInputStream(), file.getSize(), file.getContentType());

            // Save the image URL in the user's profile
            user.setUser_photo(imageUrl);
            userRepository.save(user);

            return new RedirectView("/media/"+userId);

        } catch (IOException e) {
            throw new RuntimeException("Error uploading file:"+e.getMessage());
        }
    }

    @PostMapping("/upload/post")
    public RedirectView uploadImageAsPost(@RequestParam("file") MultipartFile file, HttpSession session){
        try {
            Long userId = (Long) session.getAttribute("user_id");
            if (userId == null) {
                throw new RuntimeException("Not authorized");
            }

            String imageUrl = imageService.uploadImage(file.getInputStream(), file.getSize(), file.getContentType());
            User user = userRepository.findById(userId)
                    .orElseThrow(() -> new RuntimeException("User not found"));
            Post post = new Post(imageUrl,user,true);
            postRepository.save(post);
            return new RedirectView("/");
        } catch (IOException e) {
            throw new RuntimeException("Error uploading file:"+e.getMessage());
        }
    }
}

在上传个人资料图片的前端我添加了以下内容:

<div class="mb-3">
     <form id="image-form" th:action="@{/api/images/upload/{id}(id=${user.id})}" method="post"
                           enctype="multipart/form-data">
      <"formFile" class="form-label btn btn-primary">Upload Image</label>
      <input class="form-control" type="file" name="file" id="formFile" accept=".jpg,.jpeg,.png"
                           onchange="autoSubmitImage()" hidden/>
      </form>
 </div>

 <script th:inline="javascript">
    /*<![CDATA[*/
        const autoSubmitImage = ()=> {
          document.getElementById("image-form").submit();
        }
    /*]]>*/
</script>

结果。

Storing images for your UGC app using Spring Boot and iDrive E3

就是这个。

干杯!

以上是使用 Spring Boot 和 iDrive E3 存储 UGC 应用程序的图像的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn