Helo dunia!
Ini adalah artikel kedua tentang pengalaman saya di Makers membina klon rangkaian sosial. Pautan ke artikel pertama - https://dev.to/olnov/working-with-http-requests-in-spring-boot-5el0. Yang semasa dikhaskan untuk menyimpan imej untuk profil pengguna.
Langkah #1. Perancangan.
Sebagai sebahagian daripada MVP kami, kami memutuskan untuk melaksanakan cerita pengguna berikut:
Sebagai pengguna,
Saya mahu mengemas kini profil saya untuk memasukkan foto saya,
Supaya pengguna lain dapat mencari saya dengan mudah dalam apl
Kami juga bersetuju dengan keperluan tidak berfungsi.
Langkah #2. Analisis dan Reka Bentuk.
Kami datang dengan pilihan yang berbeza untuk tempat menyimpan imej - folder pelayan jauh, pangkalan data dan storan objek. Walaupun aplikasi kami tidak dimuatkan dengan tinggi, kami memutuskan untuk menggunakan S3 sebagai penyelesaian yang paling sesuai untuk sistem teragih. (P.S. dan saya mempunyai langganan iDrive e2 sedia ada daripada projek sebelumnya).
Dalam Pangkalan Data, hanya terdapat pautan ke URL awam storan iDrive.
Berikut ialah rajah DB:
Rajah apl peringkat tinggi:
Langkah #3. Bina.
Bahagian hujung belakang memerlukan perkara berikut untuk dilengkapkan:
Dalam pom.xml saya menambah yang berikut:
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.28.18</version> </dependency>
Kelas Perkhidmatan Imej:
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; } }
Pembolehubah sambungan Idrive disimpan dalam fail 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}
Ok, sekarang Kelas Pengawal Imej:
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()); } } }
Di bahagian hadapan untuk memuat naik imej profil saya menambah yang berikut:
<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>
Dan hasilnya.
Ini dia.
Sola!
Atas ialah kandungan terperinci Menyimpan imej untuk apl UGC anda menggunakan Spring Boot dan iDrive E3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!