世界你好!
這是關於我在 Makers 建立社交網路克隆的經歷的第二篇文章。第一篇文章的連結 - https://dev.to/olnov/working-with-http-requests-in-spring-boot-5el0。 目前的一個專門用於儲存用戶個人資料的圖像。
步驟#1。計劃。
作為 MVP 的一部分,我們決定實現以下使用者故事:
作為用戶,
我想更新我的個人資料以包含我的照片,
讓其他使用者可以輕鬆在應用程式中找到我
我們也就非功能性需求達成了一致。
步驟#2。分析和設計。
我們提出了不同的影像儲存位置選項 - 遠端伺服器資料夾、資料庫和物件儲存。儘管我們的應用程式負載不高,但我們決定使用 S3 作為分散式系統最合適的解決方案。 (P.S. 和我已經從之前的專案訂閱了 iDrive e2)。
在資料庫中,只有 iDrive 儲存的公共 URL 的連結。
這是資料庫圖:
進階應用圖:
步驟#3。構建。
後端部分需要完成以下:
在 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>
結果。
就是這個。
乾杯!
以上是使用 Spring Boot 和 iDrive E3 儲存 UGC 應用程式的圖像的詳細內容。更多資訊請關注PHP中文網其他相關文章!