E
E
Eugenue Cesarevich2021-01-21 17:35:28
Java
Eugenue Cesarevich, 2021-01-21 17:35:28

How to work with images in Java web applications?

I'm making a web application on Spring MVC - a testing system for students. The bottom line is: the student passes the tests. At the same time, a picture should be attached to each test, with a graph of a function, for example, or with an equation. I have never dealt with images in Java (somehow it happened) and now I do not quite understand how I should interact with them and store them. The question is specifically the following:

1. How to store the image? As far as I know, they can be crammed directly into PostgreSQL, but I'm leaning towards the fact that images should be saved to resources, and only links should be stored in the database.

2. How to save an image to resources for new tests? Is it normal to do this with a regular FileWriter, or is there some special way?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
Orkhan, 2021-01-21
@cot_shaurma

Good afternoon!

How to store an image? As far as I know, they can be crammed directly into PostgreSQL, but I'm leaning towards the fact that images should be saved to resources, and only links should be stored in the database.

Not the best idea to store pictures as binary in a DB. It is better, as you noted in the database, to store a link to the object, and the resource in the file system. It is possible to store files in distributed file systems (AWS, Google), but it is unlikely that you have such a budget.
Here is a simple implementation of storing images in FS.
entity
@Entity
@Data
@NoArgsConstructor
@Table(name = "attachments")
public class Attachment {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  private Long attachId;

  private String attachTitle;

  @Column(nullable = false, updatable = false)
  private LocalDate uploadDate;

  private String extension;

  private String downloadLink;

}

repository
@Repository
public interface AttachmentRepository extends JpaRepository<Attachment, Long> {}

Service
public interface AttachmentService {

  /**
   * Загрузить новый файл
   *
   * @param file
   * @param user
   * @throws IOException
   */
  Attachment addAttachment(MultipartFile file, User user) throws IOException;


  /**
   * Найти Вложение по его ID
   *
   * @param attachId
   * @return
   */
  Attachment findAttachById(Long attachId);	

  /**
   * Скачать файл
   *
   * @param uploadYear
   * @param fileName
   * @return
   * @throws MalformedURLException
   */
  Resource loadFileAsResource(String uploadYear, String fileName) throws MalformedURLException;

}

ServiceImpl
@Service
@RequiredArgsConstructor
public class AttachmentServiceImpl implements AttachmentService {

  private final AttachmentRepository attachmentRepository;
  private final AppProperties appProperties;
  private final FileTools fileTools;

  /**
   * Загрузить новый файл
   *
   * @param file
   * @param user
   * @throws IOException
   */
  @Override
  public Attachment addAttachment(MultipartFile file, User user) throws IOException {
    // Создаем директорию если ее не существует
    File uploadDir = new File(appProperties.getUploadPath());
    // Если директория uploads не существует, то создаем ее
    if (!uploadDir.exists()) {
      uploadDir.mkdirs();
    }
    String curDate = LocalDateTime.now().toString();
    // Создаем уникальное название для файла и загружаем файл
    String fileName =
        "attach_" + curDate + "_" + file.getOriginalFilename().toLowerCase().replaceAll(" ", "-");
    file.transferTo(new File(uploadDir + "/" + fileName));
    Attachment attachment = Attachment.builder()
        .attachTitle(fileName)
        .uploadDate(LocalDate.now())
        .extension(fileTools.getFileExtension(file.getOriginalFilename()))
        .downloadLink("/attachments/get/" + Year.now() + "/" + fileName)
        .build();
    attachmentRepository.save(attachment);
    return attachment;
  }


  /**
   * Найти Вложение по его ID
   *
   * @param attachId
   * @return
   */
  @Override
  public Attachment findAttachById(Long attachId) {
    return attachmentRepository
        .findById(attachId)
        .orElseThrow(() -> new AttachmentNotFoundException("Attachment not found!"));
  }


  /**
   * Скачать файл
   *
   * @param fileName
   * @return
   * @throws MalformedURLException
   */
  @Override
  public Resource loadFileAsResource( String fileName)
      throws MalformedURLException {
    Path fileStorageLocation =
        Paths.get(appProperties.getUploadPath()).toAbsolutePath().normalize();
    Path filePath = fileStorageLocation.resolve(fileName).normalize();
    return new UrlResource(filePath.toUri());
  }

}

Controller
@Controller
@RequiredArgsConstructor
@RequestMapping("/attachments")
public class AttachmentController {

  private final AttachmentService attachmentService;
  private final UserService userService;

  /**
   * Загрузить новое вложение
   *
   * @param file
   * @return
   * @throws IOException
   */
  @PostMapping(value = "/add", produces = "application/json")
  @ResponseBody
  public ResponseEntity<Map<String, String>> uploadAttachment(
      @RequestPart(value = "file") MultipartFile file)
      throws IOException {
    Attachment attachment = attachmentService.addAttachment(file);
    Map<String, String> attachmentStatus = new HashMap<>();
    attachmentStatus.put("status", "ok");
    attachmentStatus.put("attachId", attachment.getAttachId().toString());
    return ResponseEntity.ok(attachmentStatus);
  }

  /**
   * Получить ссылку на скачивание загруженного файла
   *
   * @param filename
   * @param request
   * @return
   * @throws IOException
   */
  @GetMapping("/get/{filename:.+}")
  public ResponseEntity<Resource> serveFile(
       @PathVariable String filename, HttpServletRequest request)
      throws IOException {
    Resource resource = attachmentService.loadFileAsResource(filename);
    String contentType;
    contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
    if (contentType == null) {
      contentType = "application/octet-stream";
    }
    return ResponseEntity.ok()
        .contentType(MediaType.parseMediaType(contentType))
        .header(
            HttpHeaders.CONTENT_DISPOSITION,
            "attachment; filename=\"" + resource.getFilename() + "\"")
        .body(resource);
  }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question