Merge branch 'feature/SUPPORT-8381_file_upload_back' into feature/SUPPORT-8381_file_upload

This commit is contained in:
Alexandr Shalaginov 2024-07-17 12:48:16 +03:00
commit 1f6e79466e
11 changed files with 310 additions and 46 deletions

View file

@ -99,6 +99,10 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>ru.cg.webbpm.modules</groupId>
<artifactId>inject</artifactId>

View file

@ -0,0 +1,45 @@
package ervu;
import java.util.HashMap;
import java.util.Map;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;
/**
* @author Alexandr Shalaginov
*/
@Configuration
public class KafkaProducerConfig {
@Value("${kafka.send.url:#{null}}")
private String kafkaUrl;
@Bean
public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
@Bean
public Map<String, Object> producerConfigs() {
if (this.kafkaUrl == null) {
throw new RuntimeException("Property kafka.send.url is null");
}
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, this.kafkaUrl);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return props;
}
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
}

View file

@ -0,0 +1,37 @@
package ervu.client.fileupload;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Alexandr Shalaginov
*/
@Component
public class EmployeeInfoWebDavClient {
private static final Logger logger = LoggerFactory.getLogger(EmployeeInfoWebDavClient.class);
@Value("${file.webdav.upload.url:http://localhost:5757}")
private String url;
public boolean webDavUploadFile(String filename, MultipartFile multipartFile) {
try {
HttpClient httpClient = HttpClient.newBuilder().build();
HttpRequest httpRequest = HttpRequest.newBuilder().uri(URI.create(this.url + "/" + filename))
.PUT(HttpRequest.BodyPublishers.ofByteArray(multipartFile.getBytes())).build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
return (response.statusCode() >= 200) && (response.statusCode() <= 202);
}
catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,31 @@
package ervu.controller;
import ervu.service.fileupload.EmployeeInfoFileUploadService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Alexandr Shalaginov
*/
@RestController
public class EmployeeInfoFileUploadController {
private final EmployeeInfoFileUploadService fileUploadService;
public EmployeeInfoFileUploadController(EmployeeInfoFileUploadService fileUploadService) {
this.fileUploadService = fileUploadService;
}
@RequestMapping(value = "/employee/document", method = RequestMethod.POST)
public ResponseEntity<?> saveEmployeeInformationFile(@RequestParam("file") MultipartFile multipartFile) {
if (this.fileUploadService.saveEmployeeInformationFile(multipartFile)) {
return ResponseEntity.ok("File successfully uploaded.");
}
else {
return ResponseEntity.internalServerError().body("An error occurred while uploading file.");
}
}
}

View file

@ -1,35 +0,0 @@
package ervu.controller;
import ervu.service.fileupload.FileUploadV2Service;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
import ru.cg.webbpm.modules.webkit.beans.Behavior;
/**
* @author Alexandr Shalaginov
*/
@RestController
public class FileUploadV2Controller extends Behavior {
@NotNull
public final FileUploadV2Service fileUploadV2Service;
public FileUploadV2Controller(FileUploadV2Service fileUploadV2Service) {
this.fileUploadV2Service = fileUploadV2Service;
}
@RequestMapping(value = "/file/upload", method = RequestMethod.POST)
public ResponseEntity<?> saveFile(@RequestParam("file") MultipartFile multipartFile) {
if (this.fileUploadV2Service.saveFile(multipartFile)) {
return ResponseEntity.ok("File successfully uploaded.");
}
else {
return ResponseEntity.internalServerError().body("An error occurred while uploading file.");
}
}
}

View file

@ -0,0 +1,101 @@
package ervu.service.fileupload;
import java.util.UUID;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import ervu.client.fileupload.EmployeeInfoWebDavClient;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import ru.cg.webbpm.modules.security.api.runtime.SecurityContext;
/**
* @author Alexandr Shalaginov
*/
@Service
public class EmployeeInfoFileUploadService {
private static final Logger logger = LoggerFactory.getLogger(EmployeeInfoFileUploadService.class);
private final EmployeeInfoWebDavClient fileWebDavUploadClient;
private final KafkaTemplate<String, String> kafkaTemplate;
@Value("${kafka.send.message.topic.name:employee-files}")
private String kafkaTopicName;
public EmployeeInfoFileUploadService(
EmployeeInfoWebDavClient fileWebDavUploadClient,
KafkaTemplate<String, String> kafkaTemplate) {
this.fileWebDavUploadClient = fileWebDavUploadClient;
this.kafkaTemplate = kafkaTemplate;
}
public boolean saveEmployeeInformationFile(MultipartFile multipartFile) {
String newFilename = getNewFilename(multipartFile.getOriginalFilename());
if (this.fileWebDavUploadClient.webDavUploadFile(newFilename, multipartFile)) {
String jsonMessage = getJsonKafkaMessage(
new KafkaMessage(
getCurrentUsername(),
newFilename,
multipartFile.getOriginalFilename()
)
);
return sendMessage(jsonMessage);
}
else {
logger.error("Fail upload file: {}", multipartFile.getOriginalFilename());
return false;
}
}
private boolean sendMessage(String message) {
ProducerRecord<String, String> record = new ProducerRecord<>(this.kafkaTopicName, message);
try {
this.kafkaTemplate.send(record).get();
logger.debug("Success send record: {}", record);
return true;
}
catch (Exception exception) {
logger.error("Fail send message.", exception);
return false;
}
}
private String getNewFilename(String oldFilename) {
return UUID.randomUUID() + getFileExtension(oldFilename);
}
private String getFileExtension(String filename) {
int lastIndexOf = filename.lastIndexOf(".");
if (lastIndexOf == -1) {
return "";
}
return filename.substring(lastIndexOf);
}
private String getJsonKafkaMessage(KafkaMessage kafkaMessage) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(kafkaMessage);
}
catch (JsonProcessingException e) {
throw new RuntimeException(String.format("Fail get json from: %s", kafkaMessage), e);
}
}
private String getCurrentUsername() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.isAuthenticated()) {
return auth.getName();
}
return null;
}
}

View file

@ -1,10 +0,0 @@
package ervu.service.fileupload;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Alexandr Shalaginov
*/
public interface FileUploadV2Service {
boolean saveFile(MultipartFile multipartFile);
}

View file

@ -0,0 +1,37 @@
package ervu.service.fileupload;
/**
* @author Alexandr Shalaginov
*/
class KafkaMessage {
private final String username;
private final String filename;
private final String originalFilename;
public KafkaMessage(String username, String filename, String originalFilename) {
this.username = username;
this.filename = filename;
this.originalFilename = originalFilename;
}
public String getUsername() {
return username;
}
public String getFilename() {
return filename;
}
public String getOriginalFilename() {
return originalFilename;
}
@Override
public String toString() {
return "KafkaMessage{" +
"username='" + username + '\'' +
", filename='" + filename + '\'' +
", originalFilename='" + originalFilename + '\'' +
'}';
}
}

View file

@ -49,7 +49,7 @@ export class FileUploadV2 extends InputControl {
protected isProgressBarVisible: boolean = false;
private fileInputEl: any;
private url: string = '/backend/file/upload';
private url: string = '/backend/employee/document';
private messagesService: MessagesService;
constructor(el: ElementRef, cd: ChangeDetectorRef) {

View file

@ -23,6 +23,7 @@
<webbpm-platform.version>3.174.1</webbpm-platform.version>
<wbp.overall-timeout>72000</wbp.overall-timeout>
<jasperreports.version>6.15.0</jasperreports.version>
<spring-kafka.version>2.6.13</spring-kafka.version>
</properties>
<dependencyManagement>
<dependencies>
@ -293,6 +294,11 @@
<artifactId>spring-security-kerberos-web</artifactId>
<version>${spring-security-kerberos.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>${spring-kafka.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlComponent>
<id>f6d7a9d9-acfe-4414-a835-e9625fa06fb3</id>
<name>FileUploadV2</name>
<internal>false</internal>
<versions>
<studioVersion>3.175.0-SNAPSHOT</studioVersion>
<packageVersions>
<entry>
<key>ru.cg.webbpm.packages.base.resources</key>
<value>3.174.1</value>
</entry>
</packageVersions>
</versions>
<rootObject id="5694e7c5-bbb5-4d23-be6c-7ad71b8ad38c">
<name>FileUploadV2</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="36fe7f3d-d9d5-472b-ad12-956ef734ee76">
<classRef type="TS">
<className>FileUploadV2</className>
<packageName>ervu.component.fileupload</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>displayFileSize</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>displayProgressBar</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>true</simple>
</value>
</entry>
</properties>
</scripts>
</rootObject>
</xmlComponent>