Tomcat 기본 파트 수 제한(10)에 categoryHints/walletHints를 이름마다 파트로 보내 초과 → 500. 힌트를 줄바꿈으로 합친 단일 필드로 받아 파트 3개로 축소. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -44,18 +45,33 @@ public class OcrController {
|
|||||||
return Map.of("text", text);
|
return Map.of("text", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 영수증 이미지 → AI 구조화. AI 미설정/실패/미인식이면 recognized=false 로 반환(프론트가 /receipt 폴백). */
|
/**
|
||||||
|
* 영수증 이미지 → AI 구조화. AI 미설정/실패/미인식이면 recognized=false 로 반환(프론트가 /receipt 폴백).
|
||||||
|
* 분류·계좌 후보는 멀티파트 파트 수 제한(Tomcat 기본 10개)을 피하려 '줄바꿈'으로 합친 단일 필드로 받는다.
|
||||||
|
*/
|
||||||
@PostMapping("/receipt-ai")
|
@PostMapping("/receipt-ai")
|
||||||
public ParsedEntryResponse receiptAi(
|
public ParsedEntryResponse receiptAi(
|
||||||
@RequestParam("image") MultipartFile image,
|
@RequestParam("image") MultipartFile image,
|
||||||
@RequestParam(value = "categoryHints", required = false) List<String> categoryHints,
|
@RequestParam(value = "categoryHints", required = false) String categoryHints,
|
||||||
@RequestParam(value = "walletHints", required = false) List<String> walletHints,
|
@RequestParam(value = "walletHints", required = false) String walletHints,
|
||||||
@RequestAttribute(AuthInterceptor.CURRENT_MEMBER) SessionUser current) throws IOException {
|
@RequestAttribute(AuthInterceptor.CURRENT_MEMBER) SessionUser current) throws IOException {
|
||||||
if (image == null || image.isEmpty()) {
|
if (image == null || image.isEmpty()) {
|
||||||
throw new ApiException(HttpStatus.BAD_REQUEST, "영수증 이미지를 첨부하세요.");
|
throw new ApiException(HttpStatus.BAD_REQUEST, "영수증 이미지를 첨부하세요.");
|
||||||
}
|
}
|
||||||
return aiEntryParser
|
return aiEntryParser
|
||||||
.parseReceipt(image.getBytes(), image.getContentType(), LocalDate.now(), categoryHints, walletHints)
|
.parseReceipt(image.getBytes(), image.getContentType(), LocalDate.now(),
|
||||||
|
splitLines(categoryHints), splitLines(walletHints))
|
||||||
.orElseGet(() -> ParsedEntryResponse.builder().recognized(false).build());
|
.orElseGet(() -> ParsedEntryResponse.builder().recognized(false).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 줄바꿈으로 합쳐 온 후보 문자열 → 리스트(공백 항목 제거). null/빈 값이면 빈 리스트. */
|
||||||
|
private static List<String> splitLines(String joined) {
|
||||||
|
if (joined == null || joined.isBlank()) return List.of();
|
||||||
|
List<String> out = new ArrayList<>();
|
||||||
|
for (String s : joined.split("\n")) {
|
||||||
|
String t = s.trim();
|
||||||
|
if (!t.isEmpty()) out.add(t);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user