Defer Chat Attachments

This commit is contained in:
2026-04-09 22:47:57 -06:00
parent 6b055c4364
commit 12aa06f953
11 changed files with 22 additions and 426 deletions

View File

@@ -1,50 +0,0 @@
package com.petshop.backend.controller;
import com.petshop.backend.service.ChatAttachmentService;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Map;
@RestController
@RequestMapping("/api/v1/chat/attachments")
public class ChatAttachmentController {
private final ChatAttachmentService attachmentService;
public ChatAttachmentController(ChatAttachmentService attachmentService) {
this.attachmentService = attachmentService;
}
@PostMapping
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
public ResponseEntity<?> uploadAttachment(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of("message", "File is empty"));
}
try {
return ResponseEntity.ok(attachmentService.storeAttachment(file));
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("message", "Failed to store attachment: " + e.getMessage()));
}
}
@GetMapping("/{filename}")
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
public ResponseEntity<Resource> getAttachment(@PathVariable String filename) {
try {
Resource resource = attachmentService.loadAttachmentResource(filename);
return ResponseEntity.ok()
.contentType(attachmentService.resolveMediaType(filename))
.body(resource);
} catch (IllegalArgumentException e) {
return ResponseEntity.notFound().build();
}
}
}

View File

@@ -2,10 +2,6 @@ package com.petshop.backend.dto.chat;
public class MessageRequest {
private String content;
private String attachmentUrl;
private String attachmentName;
private String attachmentMimeType;
private Long attachmentSizeBytes;
public MessageRequest() {
}
@@ -17,36 +13,4 @@ public class MessageRequest {
public void setContent(String content) {
this.content = content;
}
public String getAttachmentUrl() {
return attachmentUrl;
}
public void setAttachmentUrl(String attachmentUrl) {
this.attachmentUrl = attachmentUrl;
}
public String getAttachmentName() {
return attachmentName;
}
public void setAttachmentName(String attachmentName) {
this.attachmentName = attachmentName;
}
public String getAttachmentMimeType() {
return attachmentMimeType;
}
public void setAttachmentMimeType(String attachmentMimeType) {
this.attachmentMimeType = attachmentMimeType;
}
public Long getAttachmentSizeBytes() {
return attachmentSizeBytes;
}
public void setAttachmentSizeBytes(Long attachmentSizeBytes) {
this.attachmentSizeBytes = attachmentSizeBytes;
}
}

View File

@@ -12,10 +12,6 @@ public class MessageResponse {
private String content;
private LocalDateTime timestamp;
private Boolean isRead;
private String attachmentUrl;
private String attachmentName;
private String attachmentMimeType;
private Long attachmentSizeBytes;
public MessageResponse() {
}
@@ -38,15 +34,6 @@ public class MessageResponse {
response.setContent(message.getContent());
response.setTimestamp(message.getTimestamp());
response.setIsRead(message.getIsRead());
if (message.getAttachmentUrl() != null) {
response.setAttachmentUrl("/api/v1/chat/messages/" + message.getId() + "/attachment");
}
response.setAttachmentName(message.getAttachmentName());
response.setAttachmentMimeType(message.getAttachmentMimeType());
response.setAttachmentSizeBytes(message.getAttachmentSizeBytes());
return response;
}
@@ -105,36 +92,4 @@ public class MessageResponse {
public void setIsRead(Boolean isRead) {
this.isRead = isRead;
}
public String getAttachmentUrl() {
return attachmentUrl;
}
public void setAttachmentUrl(String attachmentUrl) {
this.attachmentUrl = attachmentUrl;
}
public String getAttachmentName() {
return attachmentName;
}
public void setAttachmentName(String attachmentName) {
this.attachmentName = attachmentName;
}
public String getAttachmentMimeType() {
return attachmentMimeType;
}
public void setAttachmentMimeType(String attachmentMimeType) {
this.attachmentMimeType = attachmentMimeType;
}
public Long getAttachmentSizeBytes() {
return attachmentSizeBytes;
}
public void setAttachmentSizeBytes(Long attachmentSizeBytes) {
this.attachmentSizeBytes = attachmentSizeBytes;
}
}

View File

@@ -22,17 +22,6 @@ public class Message {
@Column(columnDefinition = "TEXT")
private String content;
@Column(length = 255)
private String attachmentUrl;
@Column(length = 255)
private String attachmentName;
@Column(length = 100)
private String attachmentMimeType;
private Long attachmentSizeBytes;
@CreationTimestamp
@Column(nullable = false, updatable = false)
private LocalDateTime timestamp;
@@ -99,36 +88,4 @@ public class Message {
public void setIsRead(Boolean isRead) {
this.isRead = isRead;
}
public String getAttachmentUrl() {
return attachmentUrl;
}
public void setAttachmentUrl(String attachmentUrl) {
this.attachmentUrl = attachmentUrl;
}
public String getAttachmentName() {
return attachmentName;
}
public void setAttachmentName(String attachmentName) {
this.attachmentName = attachmentName;
}
public String getAttachmentMimeType() {
return attachmentMimeType;
}
public void setAttachmentMimeType(String attachmentMimeType) {
this.attachmentMimeType = attachmentMimeType;
}
public Long getAttachmentSizeBytes() {
return attachmentSizeBytes;
}
public void setAttachmentSizeBytes(Long attachmentSizeBytes) {
this.attachmentSizeBytes = attachmentSizeBytes;
}
}

View File

@@ -1,56 +0,0 @@
package com.petshop.backend.service;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
@Service
public class ChatAttachmentService {
private static final String STORED_PREFIX = "/uploads/chat/";
private final Path chatDirectory = Paths.get("uploads", "chat").toAbsolutePath().normalize();
public record AttachmentMetadata(String url, String fileName, String mimeType, long size) {}
public AttachmentMetadata storeAttachment(MultipartFile file) throws IOException {
Files.createDirectories(chatDirectory);
String originalFilename = file.getOriginalFilename();
String extension = resolveExtension(originalFilename);
String filename = UUID.randomUUID() + extension;
Path filePath = chatDirectory.resolve(filename).normalize();
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
String url = "/api/v1/chat/attachments/" + filename;
return new AttachmentMetadata(url, originalFilename, file.getContentType(), file.getSize());
}
public Resource loadAttachmentResource(String filename) {
Path filePath = chatDirectory.resolve(filename).normalize();
if (!filePath.startsWith(chatDirectory) || !Files.exists(filePath) || !Files.isRegularFile(filePath)) {
throw new IllegalArgumentException("Attachment file was not found");
}
return new PathResource(filePath);
}
public MediaType resolveMediaType(String filename) {
return MediaTypeFactory.getMediaType(filename).orElse(MediaType.APPLICATION_OCTET_STREAM);
}
private String resolveExtension(String originalFilename) {
if (originalFilename == null) return "";
int idx = originalFilename.lastIndexOf('.');
return idx < 0 ? "" : originalFilename.substring(idx);
}
}

View File

@@ -131,10 +131,6 @@ public class ChatService {
message.setConversationId(conversationId);
message.setSenderId(userId);
message.setContent(request.getContent());
message.setAttachmentUrl(request.getAttachmentUrl());
message.setAttachmentName(request.getAttachmentName());
message.setAttachmentMimeType(request.getAttachmentMimeType());
message.setAttachmentSizeBytes(request.getAttachmentSizeBytes());
message.setIsRead(false);
message = messageRepository.save(message);