[Gena Co.] Internship Project/GENA Labeling Tool

(25.03.05) Label CRUD & CSV File Download 기능 구현

Genie; 2025. 3. 6. 10:39

Label CRUD 구현

// Sample 엔터티
@Entity
@Table(name = "samples")
public class Sample extends Timestamp {
...
@Column(columnDefinition = "JSON")
@Convert(converter = ListToJsonConverter.class)
private List<String> labels;
  • 샘플과 N:M 관계를 형성할 경우 PoC단계에서 중간 테이블이 계속 생성이 될 수 있음 -> Sample 에 Json 타입으로 리스트로 지정
    • 이벤트 소싱기반 이기 때문에 중간 테이블에 비효율적으로 기록이 많이 될 수 있다는 점

File Download 기능 구현

@Transactional
public InputStreamResource getCsvFile(String datasetName) {
	// 샘플은 sample_data에서의 id 기준으로 오름차순으로 정렬
    List<Sample> samples = sampleRepository.findLatestUpdatedSampleOfDataset(datasetName);

    if (samples.isEmpty()) throw new FileProcessingException("No data found for dataset");
	
    try {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        CSVWriter csvWriter = new CSVWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
		
        // 첫번째로 얻은 데이터를 Json 객체로 바꾸고, 키를 얻어서 CSV의 컬럼, Header로 사용
        JsonObject firstSampleData = JsonParser.parseString(samples.get(0).getSampleData()).getAsJsonObject();
        String[] headers = firstSampleData.keySet().toArray(new String[0]);
        csvWriter.writeNext(headers);
		
        // Sample 마다 data을 JSON으로 만들어서 CSV 파일의 로우 데이터 하나씩 추가
        for (Sample sample : samples) {
            JsonObject sampleData = JsonParser.parseString(sample.getSampleData()).getAsJsonObject();

            String[] row = Arrays.stream(headers)
                    .map(header -> sampleData.has(header) ? sampleData.get(header).getAsString() : "")
                    .toArray(String[]::new);

            csvWriter.writeNext(row);
        }

        csvWriter.close();
		
        // 바이트타입으로 InputStreamResource 객체로 만듬
        return new InputStreamResource(new ByteArrayInputStream(out.toByteArray()));

    } catch (Exception e) {
        throw new FileProcessingException("Error generating CSV file");
    }
}
@GetMapping("/download/{dataset_name}")
public ResponseEntity<InputStreamResource> downloadCsvFile(@PathVariable(name = "dataset_name") String datasetName) {
    InputStreamResource resource = datasetService.getCsvFile(datasetName);

    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + datasetName.replace(" ", "_") + ".csv")
            .contentType(MediaType.parseMediaType("text/csv"))
            .body(resource);
}
  • 서비스단에서 나온 Resource를 헤더에 CNTENT_DIPOSITION과 미디어 타입을 지정을 해서 클라이언트가 CSV파일로 바로저장할 수 있도록 함