Storing files indexed by a database (#10174)
Creating the FileLocationService to link the FileSystemRepository to the ImageDbRepository. Removing test order Changing to BDDMockito Changing Long wrapper for @id. Changing the test names to given-when-then pattern Co-authored-by: Gilvan Ornelas Fernandes Filho <gilvan.fernandes@bairesdev.com>
This commit is contained in:
		
							parent
							
								
									1346d5f0c5
								
							
						
					
					
						commit
						d4a8a33604
					
				| @ -0,0 +1,31 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.core.io.FileSystemResource; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.web.server.ResponseStatusException; | ||||
| 
 | ||||
| @Service | ||||
| class FileLocationService { | ||||
| 
 | ||||
|     @Autowired | ||||
|     FileSystemRepository fileSystemRepository; | ||||
|     @Autowired | ||||
|     ImageDbRepository imageDbRepository; | ||||
| 
 | ||||
|     Long save(byte[] bytes, String imageName) throws Exception { | ||||
|         String location = fileSystemRepository.save(bytes, imageName); | ||||
| 
 | ||||
|         return imageDbRepository.save(new Image(imageName, location)) | ||||
|             .getId(); | ||||
|     } | ||||
| 
 | ||||
|     FileSystemResource find(Long imageId) { | ||||
|         Image image = imageDbRepository.findById(imageId) | ||||
|             .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); | ||||
| 
 | ||||
|         return fileSystemRepository.findInFileSystem(image.getLocation()); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,30 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.core.io.FileSystemResource; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.PathVariable; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RequestParam; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("file-system") | ||||
| class FileSystemImageController { | ||||
| 
 | ||||
|     @Autowired | ||||
|     FileLocationService fileLocationService; | ||||
| 
 | ||||
|     @PostMapping("/image") | ||||
|     Long uploadImage(@RequestParam MultipartFile image) throws Exception { | ||||
|         return fileLocationService.save(image.getBytes(), image.getOriginalFilename()); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping(value = "/image/{imageId}", produces = MediaType.IMAGE_JPEG_VALUE) | ||||
|     FileSystemResource downloadImage(@PathVariable Long imageId) throws Exception { | ||||
|         return fileLocationService.find(imageId); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,36 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.Date; | ||||
| 
 | ||||
| import org.springframework.core.io.FileSystemResource; | ||||
| import org.springframework.stereotype.Repository; | ||||
| 
 | ||||
| @Repository | ||||
| class FileSystemRepository { | ||||
| 
 | ||||
|     String RESOURCES_DIR = FileSystemRepository.class.getResource("/") | ||||
|         .getPath(); | ||||
| 
 | ||||
|     String save(byte[] content, String imageName) throws Exception { | ||||
|         Path newFile = Paths.get(RESOURCES_DIR + new Date().getTime() + "-" + imageName); | ||||
|         Files.createDirectories(newFile.getParent()); | ||||
| 
 | ||||
|         Files.write(newFile, content); | ||||
| 
 | ||||
|         return newFile.toAbsolutePath() | ||||
|             .toString(); | ||||
|     } | ||||
| 
 | ||||
|     FileSystemResource findInFileSystem(String location) { | ||||
|         try { | ||||
|             return new FileSystemResource(Paths.get(location)); | ||||
|         } catch (Exception e) { | ||||
|             // Handle access or file not found problems. | ||||
|             throw new RuntimeException(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,62 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.GeneratedValue; | ||||
| import javax.persistence.Id; | ||||
| import javax.persistence.Lob; | ||||
| 
 | ||||
| @Entity | ||||
| class Image { | ||||
| 
 | ||||
|     @Id | ||||
|     @GeneratedValue | ||||
|     Long id; | ||||
| 
 | ||||
|     String name; | ||||
| 
 | ||||
|     String location; | ||||
| 
 | ||||
|     @Lob | ||||
|     byte[] content; | ||||
| 
 | ||||
|     public Image() { | ||||
|     } | ||||
| 
 | ||||
|     public Image(String name, String location) { | ||||
|         this.name = name; | ||||
|         this.location = location; | ||||
|     } | ||||
| 
 | ||||
|     public byte[] getContent() { | ||||
|         return content; | ||||
|     } | ||||
| 
 | ||||
|     public void setContent(byte[] content) { | ||||
|         this.content = content; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     public String getLocation() { | ||||
|         return location; | ||||
|     } | ||||
| 
 | ||||
|     public void setLocation(String location) { | ||||
|         this.location = location; | ||||
|     } | ||||
| 
 | ||||
|     public long getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(long id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| public class ImageArchiveApplication { | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         SpringApplication.run(ImageArchiveApplication.class, args); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,46 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.core.io.ByteArrayResource; | ||||
| import org.springframework.core.io.Resource; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.PathVariable; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestParam; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
| import org.springframework.web.server.ResponseStatusException; | ||||
| 
 | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| 
 | ||||
| @RestController | ||||
| @Slf4j | ||||
| class ImageController { | ||||
| 
 | ||||
|     @Autowired | ||||
|     ImageDbRepository imageDbRepository; | ||||
| 
 | ||||
|     @PostMapping("/image") | ||||
|     long uploadImage(@RequestParam MultipartFile multipartImage) throws IOException { | ||||
|         Image dbImage = new Image(); | ||||
|         dbImage.setName(multipartImage.getOriginalFilename()); | ||||
|         dbImage.setContent(multipartImage.getBytes()); | ||||
| 
 | ||||
|         return imageDbRepository.save(dbImage) | ||||
|             .getId(); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping(value = "/image/{imageId}", produces = MediaType.IMAGE_JPEG_VALUE) | ||||
|     Resource downloadImage(@PathVariable Long imageId) { | ||||
|         byte[] image = imageDbRepository.findById(imageId) | ||||
|             .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)) | ||||
|             .getContent(); | ||||
| 
 | ||||
|         return new ByteArrayResource(image); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||
| import org.springframework.stereotype.Repository; | ||||
| 
 | ||||
| @Repository | ||||
| interface ImageDbRepository extends JpaRepository<Image, Long> { | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,69 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.mockito.BDDMockito.given; | ||||
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||||
| 
 | ||||
| import java.io.InputStream; | ||||
| import java.nio.file.Paths; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.boot.test.mock.mockito.MockBean; | ||||
| import org.springframework.core.io.FileSystemResource; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.mock.web.MockMultipartFile; | ||||
| import org.springframework.test.web.servlet.MockMvc; | ||||
| import org.springframework.test.web.servlet.MvcResult; | ||||
| import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; | ||||
| import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | ||||
| 
 | ||||
| @SpringBootTest(classes = ImageArchiveApplication.class) | ||||
| @AutoConfigureMockMvc | ||||
| class FileSystemImageIntegrationTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     MockMvc mockMvc; | ||||
| 
 | ||||
|     @MockBean | ||||
|     FileLocationService fileLocationService; | ||||
| 
 | ||||
|     @Test | ||||
|     void givenJpegImage_whenUploadIt_thenReturnItsId() throws Exception { | ||||
|         ClassLoader classLoader = ClassLoader.getSystemClassLoader(); | ||||
|         InputStream image = classLoader.getResourceAsStream("baeldung.jpeg"); | ||||
| 
 | ||||
|         MockMultipartHttpServletRequestBuilder multipartRequest = MockMvcRequestBuilders.multipart("/file-system/image") | ||||
|             .file(new MockMultipartFile("image", "baeldung", MediaType.TEXT_PLAIN_VALUE, image)); | ||||
| 
 | ||||
|         MvcResult result = mockMvc.perform(multipartRequest) | ||||
|             .andExpect(status().isOk()) | ||||
|             .andReturn(); | ||||
| 
 | ||||
|         assertThat(result.getResponse() | ||||
|             .getContentAsString()) | ||||
|                 .isEqualTo("1"); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     void givenBaeldungImage_whenDownloadIt_thenReturnTheImage() throws Exception { | ||||
|         given(fileLocationService.find(1L)) | ||||
|             .willReturn(baeldungJpegResource()); | ||||
| 
 | ||||
|         mockMvc.perform(MockMvcRequestBuilders | ||||
|             .get("/file-system/image/1") | ||||
|             .contentType(MediaType.IMAGE_JPEG_VALUE)) | ||||
|             .andExpect(status().isOk()); | ||||
|     } | ||||
| 
 | ||||
|     private FileSystemResource baeldungJpegResource() { | ||||
|         ClassLoader classLoader = ClassLoader.getSystemClassLoader(); | ||||
|         String imagePath = classLoader.getResource("baeldung.jpeg") | ||||
|             .getFile(); | ||||
| 
 | ||||
|         return new FileSystemResource(Paths.get(imagePath)); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,72 @@ | ||||
| package com.baeldung.db.indexing; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.mockito.BDDMockito.given; | ||||
| import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Paths; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.boot.test.mock.mockito.MockBean; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.mock.web.MockMultipartFile; | ||||
| import org.springframework.test.web.servlet.MockMvc; | ||||
| import org.springframework.test.web.servlet.MvcResult; | ||||
| import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; | ||||
| import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | ||||
| 
 | ||||
| @SpringBootTest(classes = ImageArchiveApplication.class) | ||||
| @AutoConfigureMockMvc | ||||
| class ImageIntegrationTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     MockMvc mockMvc; | ||||
| 
 | ||||
|     @MockBean | ||||
|     ImageDbRepository imageRepository; | ||||
| 
 | ||||
|     @Test | ||||
|     void givenBaeldungJpegImage_whenUploadIt_thenReturnItsId() throws Exception { | ||||
|         ClassLoader classLoader = ClassLoader.getSystemClassLoader(); | ||||
|         InputStream image = classLoader.getResourceAsStream("baeldung.jpeg"); | ||||
| 
 | ||||
|         MockMultipartHttpServletRequestBuilder multipartRequest = MockMvcRequestBuilders.multipart("/image") | ||||
|             .file(new MockMultipartFile("image", "baeldung", MediaType.TEXT_PLAIN_VALUE, image)); | ||||
| 
 | ||||
|         MvcResult result = mockMvc.perform(multipartRequest) | ||||
|             .andExpect(status().isOk()) | ||||
|             .andReturn(); | ||||
| 
 | ||||
|         assertThat(result.getResponse() | ||||
|             .getContentAsString()) | ||||
|                 .isEqualTo("1"); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     void givenExistingImage_whenDownloadIt_thenReturnHttpStatusOk() throws Exception { | ||||
|         given(imageRepository.findById(1L)) | ||||
|             .willReturn(Optional.of(baeldungImage())); | ||||
| 
 | ||||
|         mockMvc.perform(MockMvcRequestBuilders | ||||
|             .get("/image/1") | ||||
|             .contentType(MediaType.IMAGE_JPEG_VALUE)) | ||||
|             .andExpect(status().isOk()); | ||||
|     } | ||||
| 
 | ||||
|     private Image baeldungImage() throws IOException { | ||||
|         ClassLoader classLoader = ClassLoader.getSystemClassLoader(); | ||||
| 
 | ||||
|         Image mockImage = new Image(); | ||||
|         mockImage.setContent(Files.readAllBytes(Paths.get(classLoader.getResource("baeldung.jpeg") | ||||
|             .getFile()))); | ||||
|         return mockImage; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 9.1 KiB | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user