1 package org.imageconverter.controller;
2
3 import static java.util.stream.Collectors.joining;
4 import static org.apache.commons.lang3.StringUtils.EMPTY;
5 import static org.imageconverter.util.controllers.imageconverter.ImageConverterConst.REST_URL;
6 import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION;
7 import static org.springframework.http.HttpStatus.CREATED;
8 import static org.springframework.http.HttpStatus.NO_CONTENT;
9 import static org.springframework.http.HttpStatus.OK;
10 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
11 import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
12
13 import java.io.ByteArrayInputStream;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Optional;
18
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21
22 import org.imageconverter.application.ImageConversionService;
23 import org.imageconverter.domain.conversion.ExecutionType;
24 import org.imageconverter.domain.conversion.ImageConversion;
25 import org.imageconverter.util.controllers.imageconverter.ImageConversionPostResponse;
26 import org.imageconverter.util.controllers.imageconverter.ImageConversionResponse;
27 import org.imageconverter.util.controllers.imageconverter.ImageConverterRequest;
28 import org.imageconverter.util.controllers.imageconverter.ImageConverterRequestArea;
29 import org.imageconverter.util.controllers.imageconverter.ImageConverterRequestInterface;
30 import org.imageconverter.util.logging.Loggable;
31 import org.imageconverter.util.openapi.imageconverter.ImageConverterRestGetByIdOpenApi;
32 import org.imageconverter.util.openapi.imageconverter.ImageConverterRestGetOpenApi;
33 import org.imageconverter.util.openapi.imageconverter.ImageConverterRestPostAreaOpenApi;
34 import org.imageconverter.util.openapi.imageconverter.ImageConverterRestPostOpenApi;
35 import org.imageconverter.util.openapi.imagetype.ImageTypeRestDeleteOpenApi;
36 import org.springdoc.core.converters.models.PageableAsQueryParam;
37 import org.springframework.context.annotation.Description;
38 import org.springframework.core.io.InputStreamResource;
39 import org.springframework.data.domain.Page;
40 import org.springframework.data.domain.Pageable;
41 import org.springframework.data.jpa.domain.Specification;
42 import org.springframework.data.web.PageableDefault;
43 import org.springframework.http.MediaType;
44 import org.springframework.http.ResponseEntity;
45 import org.springframework.web.bind.annotation.DeleteMapping;
46 import org.springframework.web.bind.annotation.GetMapping;
47 import org.springframework.web.bind.annotation.PathVariable;
48 import org.springframework.web.bind.annotation.PostMapping;
49 import org.springframework.web.bind.annotation.RequestMapping;
50 import org.springframework.web.bind.annotation.RequestParam;
51 import org.springframework.web.bind.annotation.RequestPart;
52 import org.springframework.web.bind.annotation.ResponseStatus;
53 import org.springframework.web.bind.annotation.RestController;
54 import org.springframework.web.multipart.MultipartFile;
55
56 import com.turkraft.springfilter.boot.Filter;
57
58 import io.swagger.v3.oas.annotations.Parameter;
59 import io.swagger.v3.oas.annotations.media.Content;
60 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
61 import io.swagger.v3.oas.annotations.tags.Tag;
62
63
64
65
66
67
68 @SecurityRequirement(name = "BASIC")
69 @Tag(
70 name = "Image Convert",
71 description = """
72 Image Convert API - If something went wrong, please put 'trace' (for all Http methods)
73 at the end of the call to receive the stackStrace.
74 Ex: http:
75 """
76 )
77
78 @Loggable
79 @RestController
80 @Description("Controller for image converstion API")
81 @RequestMapping(REST_URL)
82 public class ImageConversionRestController {
83
84 private final ImageConversionService imageConversionService;
85
86
87
88
89
90
91 ImageConversionRestController(final ImageConversionService imageConversionService) {
92 super();
93 this.imageConversionService = imageConversionService;
94 }
95
96
97
98
99
100
101
102
103 @ImageConverterRestGetByIdOpenApi
104
105 @ResponseStatus(OK)
106 @GetMapping(value = "/{id:[\\d]*}", produces = APPLICATION_JSON_VALUE)
107 public ImageConversionResponse getById(
108 @Parameter(name = "id", description = "The image conversion id's", required = true, example = "3")
109 @PathVariable(name = "id", required = true)
110 final Long id) {
111
112 return imageConversionService.findById(id);
113 }
114
115
116
117
118
119
120
121
122 @PageableAsQueryParam
123 @ImageConverterRestGetOpenApi
124
125 @ResponseStatus(OK)
126 @GetMapping(produces = APPLICATION_JSON_VALUE)
127 public Page<ImageConversionResponse> getByFilter(
128 @Parameter(name = "filter", description = "Search's filter", required = true, example = "?filter=fileName:'image.png'")
129 @Filter
130 final Specification<ImageConversion> filter,
131
132 @PageableDefault(value = 10, page = 0)
133 final Pageable page) {
134
135 return imageConversionService.findBySpecification(filter, page);
136 }
137
138
139
140
141
142
143
144 @ImageConverterRestPostOpenApi
145
146 @ResponseStatus(CREATED)
147 @PostMapping(consumes = { MULTIPART_FORM_DATA_VALUE }, produces = APPLICATION_JSON_VALUE)
148 public ImageConversionPostResponse convert(
149 @Parameter(description = "The Image to be uploaded", content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE), required = true, example = "image.bmp")
150 @RequestPart(name = "file", required = true)
151 final MultipartFile file,
152
153 final HttpServletRequest request, final HttpServletResponse response) {
154
155 final var bytes = extractBytes(file);
156
157 final var executionType = extractExecutionType(request);
158
159 final var result = imageConversionService.convert(new ImageConverterRequest(file.getOriginalFilename(), bytes, executionType));
160
161 response.addHeader("Location", REST_URL + "/" + result.id());
162
163 return new ImageConversionPostResponse(result.text());
164 }
165
166
167
168
169
170
171
172
173
174
175
176 @ImageConverterRestPostAreaOpenApi
177
178 @ResponseStatus(CREATED)
179 @PostMapping(value = "/area", consumes = { MULTIPART_FORM_DATA_VALUE }, produces = APPLICATION_JSON_VALUE)
180 public ImageConversionPostResponse convertWithArea(
181 @Parameter(description = "The Image to be uploaded", content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE), required = true, example = "image.bmp")
182 @RequestPart(name = "file", required = true)
183 final MultipartFile file,
184
185 @Parameter(description = "The vertical position", required = true, example = "3")
186 @RequestParam(required = true)
187 final Integer xAxis,
188
189 @Parameter(description = "The horizontal position", required = true, example = "4")
190 @RequestParam(required = true)
191 final Integer yAxis,
192
193 @Parameter(description = "The width size's area", required = true, example = "56")
194 @RequestParam(required = true)
195 final Integer width,
196
197 @Parameter(description = "The height's size area ", required = true, example = "345")
198 @RequestParam(required = true)
199 final Integer height,
200
201 final HttpServletRequest request, final HttpServletResponse response) {
202
203 final var executionType = extractExecutionType(request);
204
205 final byte[] bytes = extractBytes(file);
206
207 final var result = imageConversionService.convert(new ImageConverterRequestArea(file.getOriginalFilename(), bytes, executionType, xAxis, yAxis, width, height));
208
209 response.addHeader("Location", REST_URL + "/" + result.id());
210
211 return new ImageConversionPostResponse(result.text());
212 }
213
214
215
216
217
218
219
220 @ImageConverterRestPostOpenApi
221
222 @ResponseStatus(CREATED)
223 @PostMapping(value = "/multiple", consumes = { MULTIPART_FORM_DATA_VALUE }, produces = APPLICATION_JSON_VALUE)
224 public List<ImageConversionPostResponse> convert(
225 @Parameter(description = "The Images to be uploaded", content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE), required = true, example = "image1.bmp, image2.png")
226 @RequestPart(name = "files", required = true)
227 final MultipartFile[] files,
228
229 final HttpServletRequest request,
230 final HttpServletResponse response) {
231
232 final var executionType = extractExecutionType(request);
233
234 final var listRequest = new ArrayList<ImageConverterRequestInterface>();
235
236 for (final var file : files) {
237 listRequest.add(new ImageConverterRequest(file.getOriginalFilename(), extractBytes(file), executionType));
238 }
239
240 final var result = imageConversionService.convert(listRequest);
241
242 response.addHeader("Location", result.stream().map(rst -> REST_URL + "/" + rst.id()).collect(joining(";")));
243
244 return result.stream().map(rst -> new ImageConversionPostResponse(rst.text())).toList();
245 }
246
247
248
249
250
251
252 @ImageTypeRestDeleteOpenApi
253
254 @ResponseStatus(NO_CONTENT)
255 @DeleteMapping("/{id:[\\d]*}")
256 public void delete(
257
258 @Parameter(description = "The conversion id's", example = "1000")
259 @PathVariable(name = "id", required = true)
260 final Long id) {
261
262 imageConversionService.deleteImageConversion(id);
263 }
264
265
266
267
268
269
270
271
272 @ResponseStatus(OK)
273 @GetMapping(value = "/export", produces = "txt/csv")
274 public ResponseEntity<InputStreamResource> downloadImageConversionCsv(
275 @Parameter(name = "filter", description = "Search's filter", required = true, example = "?filter=fileName:'image.png'")
276 @Filter
277 final Specification<ImageConversion> filter ) {
278
279 final var bytes = imageConversionService.findBySpecificationToCsv(filter);
280
281 final var body = new InputStreamResource(new ByteArrayInputStream(bytes));
282
283 return ResponseEntity.ok()
284 .header(CONTENT_DISPOSITION, "attachment; filename=convertions.csv")
285 .contentType(MediaType.parseMediaType("txt/csv"))
286 .body(body);
287 }
288
289
290 private byte[] extractBytes(final MultipartFile file) {
291 byte[] bytes;
292 try {
293 bytes = file.getBytes();
294 } catch (final IOException e) {
295 bytes = new byte[0];
296 }
297 return bytes;
298 }
299
300 private ExecutionType extractExecutionType(final HttpServletRequest request) {
301 final var executionTypeHeader = Optional.ofNullable(request.getHeader("Execution-Type")).orElse(EMPTY);
302
303 return ExecutionType.from(executionTypeHeader);
304 }
305 }