dev add check similar
Test Workflow / test (push) Has been cancelled

This commit is contained in:
2026-04-29 14:53:45 +07:00
parent ddaf729e18
commit aa14f0dfbf
4 changed files with 84 additions and 5 deletions
@@ -8,6 +8,9 @@ public class ImageSearchRequest {
@JsonProperty("file_id") @JsonProperty("file_id")
private String fileId; private String fileId;
@JsonProperty("check_similar_first")
private Boolean checkSimilarFirst;
@JsonProperty("page") @JsonProperty("page")
private Integer page = 1; private Integer page = 1;
@@ -14,12 +14,19 @@ import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.entity.tokenoperation.OperationType; import ru.soune.nocopy.entity.tokenoperation.OperationType;
import ru.soune.nocopy.exception.NotValidFieldException; import ru.soune.nocopy.exception.NotValidFieldException;
import ru.soune.nocopy.repository.FileEntityRepository; import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.repository.SimilarImageProjection;
import ru.soune.nocopy.service.FileSimilarityService;
import ru.soune.nocopy.service.ImageHashService;
import ru.soune.nocopy.service.file.CheckCounterService; import ru.soune.nocopy.service.file.CheckCounterService;
import ru.soune.nocopy.service.file.FileUploadService;
import ru.soune.nocopy.service.search.SearchImageService; import ru.soune.nocopy.service.search.SearchImageService;
import ru.soune.nocopy.service.tariff.TariffConstants; import ru.soune.nocopy.service.tariff.TariffConstants;
import ru.soune.nocopy.service.tariff.TariffInfoService; import ru.soune.nocopy.service.tariff.TariffInfoService;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@@ -40,6 +47,12 @@ public class ImageFoundRequestHandler implements RequestHandler {
private final SearchProperties searchProperties; private final SearchProperties searchProperties;
private final FileUploadService fileUploadService;
private final ImageHashService imageHashService;
private final FileSimilarityService fileSimilarityService;
@Override @Override
public BaseResponse handle(BaseRequest request) throws Exception { public BaseResponse handle(BaseRequest request) throws Exception {
ImageSearchRequest imageSearchRequest = objectMapper.convertValue(request.getMessageBody(), ImageSearchRequest imageSearchRequest = objectMapper.convertValue(request.getMessageBody(),
@@ -125,6 +138,35 @@ public class ImageFoundRequestHandler implements RequestHandler {
int page = imageSearchRequest.getPage() != null ? imageSearchRequest.getPage() : 1; int page = imageSearchRequest.getPage() != null ? imageSearchRequest.getPage() : 1;
int pageSize = 5; int pageSize = 5;
if (imageSearchRequest.getCheckSimilarFirst() && !allUniqueImages.isEmpty()) {
YandexSearchResponse.ImageResult image = allUniqueImages.getFirst();
String url = image.getUrl();
Path tempFile = null;
try {
tempFile = fileUploadService.downloadImageFromUrl(url);
String filePath = tempFile.toAbsolutePath().toString();
Map<String, Long> hash = imageHashService.calculateHash(Paths.get(filePath));
List<SimilarImageProjection> duplicates = fileSimilarityService.findDuplicatedByHash(hash.get("hi"),
hash.get("low"));
if (duplicates.isEmpty()) {
return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(),
"Not found similar pictures", new YandexSearchResponse());
}
} finally {
if (tempFile != null) {
try {
Files.deleteIfExists(tempFile);
} catch (IOException e) {
log.warn("Not delete temp file: {}", tempFile, e);
}
}
}
}
List<YandexSearchResponse.ImageResult> pagedResults = searchImageService.paginateResults(allUniqueImages, page, List<YandexSearchResponse.ImageResult> pagedResults = searchImageService.paginateResults(allUniqueImages, page,
pageSize * 2); pageSize * 2);
@@ -5,6 +5,10 @@ import ru.soune.nocopy.dto.file.UploadProgressResponse;
import ru.soune.nocopy.entity.file.FileEntity; import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.entity.file.FileStatus; import ru.soune.nocopy.entity.file.FileStatus;
import ru.soune.nocopy.entity.file.FileUploadSession; import ru.soune.nocopy.entity.file.FileUploadSession;
import ru.soune.nocopy.exception.DuplicateImageException;
import java.io.IOException;
import java.nio.file.Path;
public interface FileUploadService { public interface FileUploadService {
FileUploadSession initUpload(Long userId, String fileName, FileUploadSession initUpload(Long userId, String fileName,
@@ -22,4 +26,8 @@ public interface FileUploadService {
UploadProgressResponse getUploadProgress(String uploadId); UploadProgressResponse getUploadProgress(String uploadId);
FileEntity completeFileProcessing(FileUploadSession session, FileStatus status); FileEntity completeFileProcessing(FileUploadSession session, FileStatus status);
public void checkForDuplicatesSynchronously(String filePath) throws IOException, DuplicateImageException;
public Path downloadImageFromUrl(String urlString) throws IOException;
} }
@@ -6,13 +6,11 @@ import com.vrt.fileprotection.NoCopyCheckResult;
import com.vrt.fileprotection.audio.AudioCheckResult; import com.vrt.fileprotection.audio.AudioCheckResult;
import com.vrt.fileprotection.documents.DocumentCheckResult; import com.vrt.fileprotection.documents.DocumentCheckResult;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -30,7 +28,6 @@ import ru.soune.nocopy.service.cost.CostService;
import ru.soune.nocopy.service.file.FileEntityService; import ru.soune.nocopy.service.file.FileEntityService;
import ru.soune.nocopy.service.file.FileUploadService; import ru.soune.nocopy.service.file.FileUploadService;
import ru.soune.nocopy.service.file.cloud.CloudStorageService; import ru.soune.nocopy.service.file.cloud.CloudStorageService;
import ru.soune.nocopy.service.tariff.TariffConstants;
import ru.soune.nocopy.service.file.moderation.ModerationFileService; import ru.soune.nocopy.service.file.moderation.ModerationFileService;
import ru.soune.nocopy.service.notification.NotificationService; import ru.soune.nocopy.service.notification.NotificationService;
import ru.soune.nocopy.service.register.AuthService; import ru.soune.nocopy.service.register.AuthService;
@@ -38,6 +35,8 @@ import ru.soune.nocopy.service.tariff.TariffInfoService;
import ru.soune.nocopy.util.FileUtil; import ru.soune.nocopy.util.FileUtil;
import java.io.*; import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermission;
import java.security.MessageDigest; import java.security.MessageDigest;
@@ -584,8 +583,8 @@ public class FileUploadServiceImpl implements FileUploadService {
return finalFilePath.toString(); return finalFilePath.toString();
} }
private void checkForDuplicatesSynchronously(String filePath) @Override
throws IOException , DuplicateImageException { public void checkForDuplicatesSynchronously(String filePath) throws IOException , DuplicateImageException {
Path path = Paths.get(filePath); Path path = Paths.get(filePath);
Map<String, Long> hash = imageHashService.calculateHash(path); Map<String, Long> hash = imageHashService.calculateHash(path);
@@ -599,6 +598,33 @@ public class FileUploadServiceImpl implements FileUploadService {
} }
} }
public Path downloadImageFromUrl(String urlString) throws IOException {
URL url = new URL(urlString);
String extension = ".tmp";
String path = url.getPath();
int lastDot = path.lastIndexOf('.');
if (lastDot > 0) {
String ext = path.substring(lastDot).toLowerCase();
if (ext.matches("\\.(jpg|jpeg|png|gif|bmp|webp)")) {
extension = ext;
}
}
Path tempFile = Files.createTempFile("upload_check_", extension);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);
try (InputStream in = connection.getInputStream()) {
Files.copy(in, tempFile, StandardCopyOption.REPLACE_EXISTING);
}
return tempFile;
}
private UploadProgressResponse handleExistingChunk(FileUploadSession session, private UploadProgressResponse handleExistingChunk(FileUploadSession session,
Integer chunkNumber, Integer chunkNumber,
MultipartFile chunkFile, MultipartFile chunkFile,