Skip to content

Commit

Permalink
Формы. Загрузка файла на сервер. [#504855]
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelZalogin committed Mar 19, 2023
1 parent 57b6809 commit f31efb6
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 36 deletions.
28 changes: 28 additions & 0 deletions src/main/java/ru/mch/dreamjob/controller/FileController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.mch.dreamjob.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.mch.dreamjob.service.FileService;

@RestController
@RequestMapping("/files")
public class FileController {

private final FileService fileService;

public FileController(FileService fileService) {
this.fileService = fileService;
}

@GetMapping("/{id}")
public ResponseEntity<?> getById(@PathVariable int id) {
var contentOptional = fileService.getFileById(id);
if (contentOptional.isEmpty()) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(contentOptional.get().getContent());
}
}
28 changes: 20 additions & 8 deletions src/main/java/ru/mch/dreamjob/controller/VacancyController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import ru.mch.dreamjob.dto.FileDto;
import ru.mch.dreamjob.entity.Vacancy;
import ru.mch.dreamjob.service.CityService;
import ru.mch.dreamjob.service.VacancyService;
Expand Down Expand Up @@ -33,9 +35,14 @@ public String getCreationPage(Model model) {
}

@PostMapping("/create")
public String create(@ModelAttribute Vacancy vacancy) {
vacancyService.save(vacancy);
return "redirect:/vacancies";
public String create(@ModelAttribute Vacancy vacancy, @RequestParam MultipartFile file, Model model) {
try {
vacancyService.save(vacancy, new FileDto(file.getOriginalFilename(), file.getBytes()));
return "redirect:/vacancies";
} catch (Exception exception) {
model.addAttribute("message", exception.getMessage());
return "errors/404";
}
}

@GetMapping("/{id}")
Expand All @@ -51,13 +58,18 @@ public String getById(Model model, @PathVariable int id) {
}

@PostMapping("/update")
public String update(@ModelAttribute Vacancy vacancy, Model model) {
var isUpdated = vacancyService.update(vacancy);
if (!isUpdated) {
model.addAttribute("message", "Вакансия с указанным идентификатором не найдена");
public String update(@ModelAttribute Vacancy vacancy, @RequestParam MultipartFile file, Model model) {
try {
var isUpdated = vacancyService.update(vacancy, new FileDto(file.getOriginalFilename(), file.getBytes()));
if (!isUpdated) {
model.addAttribute("message", "Вакансия с указанным идентификатором не найдена");
return "errors/404";
}
return "redirect:/vacancies";
} catch (Exception exception) {
model.addAttribute("message", exception.getMessage());
return "errors/404";
}
return "redirect:/vacancies";
}

@GetMapping("/delete/{id}")
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/ru/mch/dreamjob/dto/FileDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.mch.dreamjob.dto;

public class FileDto {
private String name;

private byte[] content;

public FileDto(String name, byte[] content) {
this.name = name;
this.content = content;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public byte[] getContent() {
return content;
}

public void setContent(byte[] content) {
this.content = content;
}
}
58 changes: 58 additions & 0 deletions src/main/java/ru/mch/dreamjob/entity/File.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ru.mch.dreamjob.entity;

import java.util.Objects;

public class File {

private int id;

private String name;

private String path;

public File(String name, String path) {
this.name = name;
this.path = path;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
File file = (File) o;
return id == file.id && Objects.equals(path, file.path);
}

@Override
public int hashCode() {
return Objects.hash(id, path);
}
}
13 changes: 12 additions & 1 deletion src/main/java/ru/mch/dreamjob/entity/Vacancy.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ public class Vacancy {

private int cityId;

private int fileId;

public Vacancy() {
}

public Vacancy(int id, String title, String description, boolean visible, int cityId) {
public Vacancy(int id, String title, String description, boolean visible, int cityId, int fileId) {
this.id = id;
this.title = title;
this.description = description;
this.visible = visible;
this.cityId = cityId;
this.fileId = fileId;
}

public int getId() {
Expand Down Expand Up @@ -76,6 +79,14 @@ public void setCityId(int cityId) {
this.cityId = cityId;
}

public int getFileId() {
return fileId;
}

public void setFileId(int fileId) {
this.fileId = fileId;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/ru/mch/dreamjob/repository/FileRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ru.mch.dreamjob.repository;

import ru.mch.dreamjob.entity.File;

import java.util.Optional;

public interface FileRepository {

File save(File file);

Optional<File> findById(int id);

boolean deleteById(int id);
}
34 changes: 34 additions & 0 deletions src/main/java/ru/mch/dreamjob/repository/MemoryFileRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ru.mch.dreamjob.repository;

import org.springframework.stereotype.Repository;
import ru.mch.dreamjob.entity.File;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Repository
public class MemoryFileRepository implements FileRepository {

private final AtomicInteger nextId = new AtomicInteger(0);

private final Map<Integer, File> files = new ConcurrentHashMap<>();

@Override
public File save(File file) {
file.setId(nextId.incrementAndGet());
files.put(file.getId(), file);
return file;
}

@Override
public Optional<File> findById(int id) {
return Optional.ofNullable(files.get(id));
}

@Override
public boolean deleteById(int id) {
return files.remove(id) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ public class MemoryVacancyRepository implements VacancyRepository {
private final Map<Integer, Vacancy> vacancies = new HashMap<>();

private MemoryVacancyRepository() {
save(new Vacancy(0, "Intern Java Developer", "description", false, 1));
save(new Vacancy(0, "Junior Java Developer", "description", false, 1));
save(new Vacancy(0, "Junior+ Java Developer", "description", false, 1));
save(new Vacancy(0, "Middle Java Developer", "description", false, 2));
save(new Vacancy(0, "Middle+ Java Developer", "description", false, 2));
save(new Vacancy(0, "Senior Java Developer", "description", false, 3));
save(new Vacancy(0, "Intern Java Developer", "description", false, 1,0));
save(new Vacancy(0, "Junior Java Developer", "description", false, 1,0));
save(new Vacancy(0, "Junior+ Java Developer", "description", false, 1,0));
save(new Vacancy(0, "Middle Java Developer", "description", false, 2,0));
save(new Vacancy(0, "Middle+ Java Developer", "description", false, 2,0));
save(new Vacancy(0, "Senior Java Developer", "description", false, 3,0));
}

@Override
Expand All @@ -44,7 +44,8 @@ public boolean update(Vacancy vacancy) {
vacancy.getTitle(),
vacancy.getDescription(),
vacancy.getVisible(),
vacancy.getCityId()))
vacancy.getCityId(),
vacancy.getFileId()))
!= null;
}

Expand Down
15 changes: 15 additions & 0 deletions src/main/java/ru/mch/dreamjob/service/FileService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ru.mch.dreamjob.service;

import ru.mch.dreamjob.dto.FileDto;
import ru.mch.dreamjob.entity.File;

import java.util.Optional;

public interface FileService {

File save(FileDto fileDto);

Optional<FileDto> getFileById(int id);

boolean deleteById(int id);
}
92 changes: 92 additions & 0 deletions src/main/java/ru/mch/dreamjob/service/SimpleFileService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package ru.mch.dreamjob.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import ru.mch.dreamjob.dto.FileDto;
import ru.mch.dreamjob.entity.File;
import ru.mch.dreamjob.repository.FileRepository;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.UUID;

@Service
public class SimpleFileService implements FileService {

private final FileRepository fileRepository;

private final String storageDirectory;

public SimpleFileService(FileRepository fileRepository,
@Value("${file.directory}") String storageDirectory) {
this.fileRepository = fileRepository;
this.storageDirectory = storageDirectory;
createStorageDirectory(storageDirectory);
}

private void createStorageDirectory(String path) {
try {
Files.createDirectories(Path.of(path));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public File save(FileDto fileDto) {
var path = getNewFilePath(fileDto.getName());
writeFileBytes(path, fileDto.getContent());
return fileRepository.save(new File(fileDto.getName(), path));
}

private String getNewFilePath(String sourceName) {
return storageDirectory + java.io.File.separator + UUID.randomUUID() + sourceName;
}

private void writeFileBytes(String path, byte[] content) {
try {
Files.write(Path.of(path), content);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public Optional<FileDto> getFileById(int id) {
var fileOptional = fileRepository.findById(id);
if (fileOptional.isEmpty()) {
return Optional.empty();
}
var content = readFileAsBytes(fileOptional.get().getPath());
return Optional.of(new FileDto(fileOptional.get().getName(), content));
}

private byte[] readFileAsBytes(String path) {
try {
return Files.readAllBytes(Path.of(path));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public boolean deleteById(int id) {
var fileOptional = fileRepository.findById(id);
if (fileOptional.isEmpty()) {
return false;
}
deleteFile(fileOptional.get().getPath());
return fileRepository.deleteById(id);
}

private void deleteFile(String path) {
try {
Files.deleteIfExists(Path.of(path));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

}
Loading

0 comments on commit f31efb6

Please sign in to comment.