Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
FROM openjdk:17-jdk
FROM eclipse-temurin:17-jdk

RUN apt-get update \
&& apt-get install -y --no-install-recommends libreoffice \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

COPY build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public class Lecture extends BaseEntity {
@Column(name = "audio_url")
private String audioUrl;

@Column(name = "is_lecture_start")
private Boolean isLectureStart;

@Column(name = "save_audio")
private Boolean saveAudio;

@Column(name = "lecture_date", nullable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,25 +152,28 @@ public void deleteLecture(UUID lectureId) {

//녹음본 저장
public LectureRecordingResponseDTO uploadLectureRecording(UUID lectureId, MultipartFile file) {

Lecture lecture = lectureRepository.findById(lectureId)
.orElseThrow(() -> new LectureException(LectureErrorCode.LECTURE_NOT_FOUND));

String key = "recordings/" + lectureId +"/" + UUID.randomUUID() + "/" + file.getOriginalFilename();
String safeLectureName = lecture.getLectureName().replaceAll("\\s+", "_");
String uploadFileName = safeLectureName + ".mp3";

String key = "recordings/" + lectureId + "/" + UUID.randomUUID() + "/" + uploadFileName;

try {
s3Service.uploadFile(file, key); // private 업로드
s3Service.uploadFile(file, key);
} catch (IOException e) {
throw new S3Exception(S3ErrorCode.UPLOAD_FAIL);
}

lecture.setAudioUrl(key);
lectureRepository.save(lecture);

String audioName = key.substring(key.lastIndexOf('/') + 1);
lecture.setSaveAudio(true);

return LectureRecordingResponseDTO.builder()
.lectureId(lecture.getId())
.audioName(audioName)
.audioName(uploadFileName)
.audioUrl(s3Service.getPresignedUrl(key))
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.example.backend.domain.lectureNote.converter;

import org.springframework.web.multipart.MultipartFile;
import java.io.*;

public class FileToMultipartFileConverter implements MultipartFile {

private final File file;
private final String contentType;

// file -> multipartFile 변환
public FileToMultipartFileConverter(File file, String contentType) {
this.file = file;
this.contentType = contentType;
}

@Override
public String getName() {
return file.getName();
}

@Override
public String getOriginalFilename() {
return file.getName();
}

@Override
public String getContentType() {
return contentType;
}

@Override
public boolean isEmpty() {
return file.length() == 0;
}

@Override
public long getSize() {
return file.length();
}

@Override
public byte[] getBytes() throws IOException {
return java.nio.file.Files.readAllBytes(file.toPath());
}

@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(file);
}

@Override
public void transferTo(File dest) throws IOException {
try (InputStream in = getInputStream(); OutputStream out = new FileOutputStream(dest)) {
in.transferTo(out);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.example.backend.domain.lectureNote.converter;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;

@Component
public class LibreOfficeConverter {

// pptx -> pdf 변환
public File convertPptxToPdf(File pptxFile) throws IOException {
try {
String outputDir = pptxFile.getParent();

String baseName = pptxFile.getName().replaceAll("(?i)\\.pptx$", "");
File outputPdf = new File(outputDir, baseName + ".pdf");

ProcessBuilder pb = new ProcessBuilder(
"libreoffice", "--headless",
"--convert-to", "pdf:writer_pdf_Export",
pptxFile.getAbsolutePath(),
"--outdir", outputDir
);
Process process = pb.start();
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IOException("LibreOffice 변환 실패: exitCode=" + exitCode);
}

if (!outputPdf.exists()) {
throw new IOException("LibreOffice 변환 실패: 출력 PDF 없음");
}

return outputPdf;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("LibreOffice 변환 중 인터럽트 발생", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.example.backend.domain.classroom.exception.ClassroomErrorCode;
import org.example.backend.domain.classroom.exception.ClassroomException;
import org.example.backend.domain.classroom.repository.ClassroomRepository;
import org.example.backend.domain.lectureNote.converter.FileToMultipartFileConverter;
import org.example.backend.domain.lectureNote.converter.LibreOfficeConverter;
import org.example.backend.domain.lectureNote.dto.response.LectureNoteKeyResponseDTO;
import org.example.backend.domain.lectureNote.dto.response.LectureNoteResponseDTO;
import org.example.backend.domain.lectureNote.entity.LectureNote;
Expand All @@ -17,6 +19,7 @@
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -29,31 +32,67 @@ public class LectureNoteServiceImpl implements LectureNoteService {

private final S3Service s3Service;
private final LectureNoteRepository lectureNoteRepository;
private final ClassroomRepository classroomRepository; // ✅ 추가
private final ClassroomRepository classroomRepository;
private final LectureNoteMappingRepository lectureNoteMappingRepository;
private final LibreOfficeConverter libreOfficeConverter;

public List<LectureNote> uploadLectureNotes(UUID classId, List<MultipartFile> files) throws IOException {
// 1. 여러 파일에 대해 처리
List<LectureNote> lectureNotes = new ArrayList<>();

// 2. 각 파일 업로드 처리
for (MultipartFile file : files) {
// 1) S3에 업로드
String key = "lecture_note/" + classId + "/" + UUID.randomUUID() + "/" + file.getOriginalFilename();
String fileUrl = s3Service.uploadFile(file, key);

// 2) classId로 Classroom 엔티티 조회
Classroom classroom = classroomRepository.findById(classId)
.orElseThrow(() -> new ClassroomException(ClassroomErrorCode.CLASS_NOT_FOUND));

// 3) LectureNote 객체 생성
LectureNote lectureNote = LectureNote.builder()
.noteUrl(key)
.classroom(classroom) // Classroom 객체 넣기
.build();

// 4) LectureNote 저장
lectureNotes.add(lectureNoteRepository.save(lectureNote));
String originalFilename = Objects.requireNonNull(file.getOriginalFilename(), "파일명이 필요합니다");
boolean isPptx = originalFilename.toLowerCase().endsWith(".pptx");

File tempSrc = null;
File convertedPdf = null;
String uploadFileName;
String key;
MultipartFile pdfMultipart;

try {
if (isPptx) {
// MultipartFile -> File
tempSrc = new File(System.getProperty("java.io.tmpdir"), originalFilename);
file.transferTo(tempSrc);

try {
// PPTX → PDF 변환
convertedPdf = libreOfficeConverter.convertPptxToPdf(tempSrc);

// File -> MultipartFile
pdfMultipart = new FileToMultipartFileConverter(convertedPdf, "application/pdf");
} catch (Exception e) {
throw new IOException("PPTX→PDF 변환 실패: " + originalFilename, e);
}

uploadFileName = convertedPdf.getName();

// S3 업로드
key = "lecture_note/" + classId + "/" + UUID.randomUUID() + "/" + uploadFileName;
s3Service.uploadFile(pdfMultipart, key);

} else {
// pptx 외 다른 파일들 그대로 업로드
uploadFileName = originalFilename;
key = "lecture_note/" + classId + "/" + UUID.randomUUID() + "/" + uploadFileName;
s3Service.uploadFile(file, key);
}

Classroom classroom = classroomRepository.findById(classId)
.orElseThrow(() -> new ClassroomException(ClassroomErrorCode.CLASS_NOT_FOUND));

LectureNote lectureNote = LectureNote.builder()
.noteUrl(key)
.classroom(classroom)
.build();

lectureNotes.add(lectureNoteRepository.save(lectureNote));

} finally {
// pdf로 변환하며 생긴 임시 파일 삭제
if (tempSrc != null && tempSrc.exists()) tempSrc.delete();
if (convertedPdf != null && convertedPdf.exists()) convertedPdf.delete();
}
}

return lectureNotes;
Expand Down