알쓸전컴(알아두면 쓸모있는 전자 컴퓨터)

drag and drop 파일 업로더 서버 파트 (vue-simple-uploader) 본문

Web /Spring Framework tip

drag and drop 파일 업로더 서버 파트 (vue-simple-uploader)

백곳 2018. 3. 3. 10:22

vue-simple-uploader (Server 파트)



simple-uploader 을 사용 하기 위해서는 먼저 POST 로 전송온 request 객체를  multipartHttpServletRequest 으로 변환 해줘야 합니다. 


multipartHttpServletRequest 을 사용 하기 위해서는 


1.pom.xml


            <dependency>

    <groupId>commons-io</groupId>

    <artifactId>commons-io</artifactId>

    <version>2.0.1</version>

</dependency>

 

<dependency>

    <groupId>commons-fileupload</groupId>

    <artifactId>commons-fileupload</artifactId>

    <version>1.2.2</version>

</dependency>


추가해 줍니다. 


2.wepapp->WEB-INF->spring->appServlet->servlet-context.xml  


<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<beans:property name="maxUploadSize" value="-1" /> 

</beans:bean>


bean을 추가해 줍니다. 


여기서 옵션으로는 

maxUploadSize(최대업로드 가능한 바이트크기)

maxInMemorySize(디스크에 임시 파일을 생성하기 전에 메모리에 보관할수있는 최대 바이트 크기)

defaultEncoding(요청을 파싱할 때 사용할 캐릭터 인코딩. 기본값 ISO-8859-1)



해당 정도가 있습니다.


일단 저는  Controller  에서 


@RequestMapping(value = "/suggestion_file_upload", method = RequestMethod.POST)

public void insertBoard_attach_POST(HttpServletRequest request, HttpServletResponse response)  {

try {

suggestion_dao.insertBoard_acttach1(request,response);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return;

}




그리고 실제 구현 하는 쪽에서는 



import java.util.HashSet;

import java.util.Set;


public class FileInfo {

private final Set<Integer> uploadedChunks = new HashSet<>();


  public boolean isUploadFinished(int flowTotalChunks) {

    return this.uploadedChunks.size() == flowTotalChunks;

  }


  public boolean containsChunk(int flowChunkNumber) {

    return this.uploadedChunks.contains(flowChunkNumber);

  }


  public void addUploadedChunk(int flowChunkNumber) {

    this.uploadedChunks.add(flowChunkNumber);

  }

}



private final Map<String, FileInfo> fileInfos = new ConcurrentHashMap<>();



public synchronized void insertBoard_acttach1(HttpServletRequest request, HttpServletResponse response)

throws Exception {

// TODO Auto-generated method stub

MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;

int flowChunkNumber = Integer.parseInt(multipartHttpServletRequest.getParameter("chunkNumber"));

int flowTotalChunks = Integer.parseInt(multipartHttpServletRequest.getParameter("totalChunks"));

int flowChunkSize = Integer.parseInt(multipartHttpServletRequest.getParameter("chunkSize"));

int flowTotalSize = Integer.parseInt(multipartHttpServletRequest.getParameter("totalSize"));

String flowIdentifier = multipartHttpServletRequest.getParameter("identifier");

String flowFilename = multipartHttpServletRequest.getParameter("filename");

String relativePath = multipartHttpServletRequest.getParameter("relativePath");

String doc_number = multipartHttpServletRequest.getParameter("doc_number");

MultipartFile file = multipartHttpServletRequest.getFile("file");

System.out.println("flowIdentifier = " + flowIdentifier);

System.out.println("flowFilename = " + flowFilename);

System.out.println("doc_number = " +doc_number);



FileInfo fileInfo = this.fileInfos.get(flowIdentifier);

if (fileInfo == null) {

fileInfo = new FileInfo();

this.fileInfos.put(flowIdentifier, fileInfo);

}

String uploadDirectory = "/var/lib/tomcat8/webapps/suggestion_board/" + doc_number;


File file1 = new File(uploadDirectory);

if (!file1.exists()) {

file1.mkdirs();

}


Path identifierFile = Paths.get(uploadDirectory, flowIdentifier);

// try - Closeable 문법을 사용함

try (RandomAccessFile raf = new RandomAccessFile(identifierFile.toString(), "rw");

InputStream is = file.getInputStream()) {

raf.seek((flowChunkNumber - 1) * flowChunkSize);


long readed = 0;

long content_length = file.getSize();

byte[] bytes = new byte[1024 * 100];

while (readed < content_length) {

int r = is.read(bytes);

if (r < 0) {

break;

}

raf.write(bytes, 0, r);

readed += r;

}

}


fileInfo.addUploadedChunk(flowChunkNumber);


if (fileInfo.isUploadFinished(flowTotalChunks)) {

Path uploadedFile = Paths.get(uploadDirectory, flowFilename);

int j = 0;

while (uploadedFile.toFile().exists()) {

String[] file_names = flowFilename.split("\\.");


if (file_names.length > 1) {

flowFilename = file_names[0] + j + "." + file_names[1];

} else {

flowFilename = file_names[0] + j;

}

uploadedFile = Paths.get(uploadDirectory, flowFilename);

}


Files.move(identifierFile, uploadedFile, StandardCopyOption.ATOMIC_MOVE);

this.fileInfos.remove(flowIdentifier);



}

response.setStatus(HttpStatus.OK.value());


}


위와 같이 코딩해 주었습니다. 


flow.js 대응 spring framework 코드를 참고 하여 작성 하였습니다. 


디버깅을 해보면 1MB 씩 다운로드 파일이 분할되어 송신 됩니다. 


그래서 각각의 분할된 파일을 파일내 적정 위치에 써줘야 되는 작업이 필요합니다. 


그래서 chuck 정보 들이 필요 합니다. 



Comments