자바 서블릿 예제
주의
서버 보안을 위해 파일 업로드 및 문서 임포트 처리를 구현할 때 아래 가이드를 참고합니다.
1. 서블릿 구성
참고
Servlet 3.0 이상에서는
@WebServlet애너테이션을 대신 사용할 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>synapeditor</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>ImportServlet</servlet-name>
<servlet-class>com.synap.synapeditor.ImportServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImportServlet</servlet-name>
<url-pattern>/importDoc</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.synap.synapeditor.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/uploadFile</url-pattern>
</servlet-mapping>
</web-app>
2. 이미지 및 Video 파일 업로드
주의
아래 샘플 코드의 파일 업로드 부분은 의도적으로 최소화되어 있으며, 적절한 보안 처리가 적용되어 있지 않습니다.
파일 업로드는 프로젝트에 이미 구현된 기능을 사용하고, 아래 코드는 에디터 연동 부분만 참고합니다.
import com.google.gson.GsonBuilder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.*;
import java.util.*;
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String UPLOAD_DIR_REL_PATH = "uploads";
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3;
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40;
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (!ServletFileUpload.isMultipartContent(request)) return;
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(MEMORY_THRESHOLD);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
upload.setFileSizeMax(MAX_FILE_SIZE);
upload.setSizeMax(MAX_REQUEST_SIZE);
String ROOT_ABS_PATH = request.getSession().getServletContext().getRealPath("");
String UPLOAD_DIR_ABS_PATH = ROOT_ABS_PATH + File.separator + UPLOAD_DIR_REL_PATH;
makeDirectory(UPLOAD_DIR_ABS_PATH);
String storeFileName = "";
try {
List<FileItem> items = upload.parseRequest(request);
if (items != null) {
for (FileItem item : items) {
if (item.isFormField()) continue;
String ext = item.getName().substring(item.getName().lastIndexOf('.'));
storeFileName = UUID.randomUUID().toString() + ext;
item.write(new File(UPLOAD_DIR_ABS_PATH + File.separator + storeFileName));
}
}
} catch (Exception ex) { ex.printStackTrace(); }
Map<String, Object> map = new HashMap<>();
map.put("uploadPath", "uploads/" + storeFileName);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(new GsonBuilder().create().toJson(map));
out.flush();
}
private static void makeDirectory(String dirPath) {
File dir = new File(dirPath);
if (!dir.exists()) dir.mkdir();
}
}
3. HWP / Word / 엑셀 문서 임포트
주의
아래 샘플 코드의 파일 업로드 부분은 의도적으로 최소화되어 있으며, 적절한 보안 처리가 적용되어 있지 않습니다.
파일 업로드는 프로젝트에 이미 구현된 기능을 사용하고, 아래 코드는 에디터 연동 부분만 참고합니다.
import com.google.gson.GsonBuilder;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.*;
import java.util.*;
import java.util.zip.InflaterInputStream;
public class ImportServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String UPLOAD_DIR_REL_PATH = "import";
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3;
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40;
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (!ServletFileUpload.isMultipartContent(request)) return;
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(MEMORY_THRESHOLD);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
upload.setFileSizeMax(MAX_FILE_SIZE);
upload.setSizeMax(MAX_REQUEST_SIZE);
String ROOT_ABS_PATH = request.getSession().getServletContext().getRealPath("");
String UPLOAD_DIR_ABS_PATH = ROOT_ABS_PATH + File.separator + UPLOAD_DIR_REL_PATH;
makeDirectory(UPLOAD_DIR_ABS_PATH);
String storeFileAbsPath = "";
try {
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : items) {
if (item.isFormField()) continue;
String fileName = item.getName();
String contentType = item.getContentType();
String ext = "";
if (contentType != null) ext = "." + contentType.substring(contentType.lastIndexOf('/') + 1);
else if (fileName.lastIndexOf('.') > 0) ext = fileName.substring(fileName.lastIndexOf('.'));
if (ext.contains(".jpeg")) ext = ".jpg";
String storeFileName = UUID.randomUUID().toString() + ext;
storeFileAbsPath = UPLOAD_DIR_ABS_PATH + File.separator + storeFileName;
item.write(new File(storeFileAbsPath));
}
} catch (Exception ex) { ex.printStackTrace(); }
Calendar cal = Calendar.getInstance();
String yearMonth = String.format("%04d%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1);
String uuid = UUID.randomUUID().toString();
String outputDirAbsPath = UPLOAD_DIR_ABS_PATH + File.separator + yearMonth + File.separator + uuid;
makeDirectory(outputDirAbsPath);
executeConverter(storeFileAbsPath, outputDirAbsPath);
deleteFile(storeFileAbsPath);
String pbAbsPath = outputDirAbsPath + File.separator + "document.pb";
Integer[] serializedData = serializePbData(pbAbsPath);
deleteFile(pbAbsPath);
Map<String, Object> map = new HashMap<>();
map.put("serializedData", serializedData);
map.put("importPath", UPLOAD_DIR_REL_PATH + "/" + yearMonth + "/" + uuid);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(new GsonBuilder().create().toJson(map));
out.flush();
}
protected static int executeConverter(String inputFilePath, String outputPath) {
String SEDOC_CONVERTER_DIR_ABS_PATH = "absolute/path/to/converter/dir";
String FONT_DIR_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "fonts";
String TEMP_DIR_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "temp";
String SEDOC_CONVERTER_ABS_PATH = SEDOC_CONVERTER_DIR_ABS_PATH + File.separator + "sedocConverter_exe";
// Windows: "sedocConverter.exe"
makeDirectory(TEMP_DIR_ABS_PATH);
makeDirectory(FONT_DIR_ABS_PATH);
String[] cmd = { SEDOC_CONVERTER_ABS_PATH, "-f", FONT_DIR_ABS_PATH, inputFilePath, outputPath, TEMP_DIR_ABS_PATH };
try {
Timer t = new Timer();
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
Process proc = pb.start();
TimerTask killer = new TimeoutProcessKiller(proc);
t.schedule(killer, 20000);
int exitValue = proc.waitFor();
killer.cancel();
return exitValue;
} catch (Exception e) { e.printStackTrace(); return -1; }
}
protected static Integer[] serializePbData(String pbFilePath) throws IOException {
List<Integer> serialized = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(pbFilePath)) {
fis.skip(16);
try (InflaterInputStream ifis = new InflaterInputStream(fis)) {
byte[] buffer = new byte[1024];
int n;
while ((n = ifis.read(buffer)) != -1) {
for (int i = 0; i < n; i++) serialized.add(buffer[i] & 0xFF);
}
}
}
return serialized.toArray(new Integer[0]);
}
private static void deleteFile(String path) {
File f = new File(path);
if (f.exists()) f.delete();
}
private static void makeDirectory(String dirPath) {
File dir = new File(dirPath);
if (!dir.exists()) dir.mkdir();
}
private static class TimeoutProcessKiller extends TimerTask {
private final Process p;
public TimeoutProcessKiller(Process p) { this.p = p; }
@Override public void run() { p.destroy(); }
}
}