본문 바로가기
Backend/JAVA

[JAVA] byte[] to File, File to MultipartFile (fin. byte[] to MultipartFile)

by 지구 2020. 9. 9.

타 API 와 통신해서 AWS S3 에 업로드 할 일이 생겼다.

MSA 에 맞춰서 다른 팀에서 S3 에 업로드하는 API 를 뚫어줬는데,
업로드 할 binary file 데이터 타입을 MultipartFile 로 만들어주셨다..

 

그렇기에 내가 할 일이란

타 API 와 통신 -> byte array 겟! -> File 객체로 변환 -> MultipartFile 객체로 변환하는 것이었다.

여기서 중요했던건 ★ no disc , in memory(buff) 에 초점을 맞췄다는 점이다.

왜냐면 통신해서 받은 데이터를 S3 에 업로드할건데 굳이 was 에 올릴 필요가 없었기 때문에 !!
( 사실은 일정 환경 이상에서 디렉토리 핸들링 권한이 없어서 was 에 저장 자체가 불가능했음.. )

(byte[] -> MultipartFile 로 바로 변환하고 싶었지만 도저히 각도 안나오고 방법이 없어서 중간단계로 File 을 거쳤다)

 

// !-- 메모리에 저장하기 위해서는 OutputStream 말고 ByteArrayOutputStream 을 써야한다. --!
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(totalCnt)) {

	// byte[] data size each
    for () {
    	// byte[] read
    	...
        
        // byte 하나하나 읽으면서 ByteArrayOutpurStream 에 저장
        while() {
        	...
            byteArrayOutputStream.write(byteArray);
            byteArrayOutputStream.flush();
        }
    }
    
    // 읽은 파일은 S3 업로드하기 위해 MultipartFile 객체로 변환한다
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    MultipartFile multipartFile = new MockMultipartFile("fileName", byteArrayInputStream.readAllBytes());
    
    // !-- MockMultipartFile 은 원래 테스트용으로 만들어졌으나 MultipartFile 객체를 생성하기 위해 사용하기도 한다. --!
}

위 코드에서 중요한 객체

1. ByteArrayOutputStream
2. ByteArrayInputStream
3. new MockMultipartFile() -> 참고

 

MockMultipartFile

Transfer the received file to the given destination file. This may either move the file in the filesystem, copy the file in the filesystem, or save memory-held contents to the destination file. If the destination file already exists, it will be deleted fir

docs.spring.io

 

하지만 이 글을 작성하기로 마음먹은건 그 이후다..
내가 생성한 MultipartFile 을 API 통신하려고 보냈더니 얘가 자꾸 500 에러가 났었다.

No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.web.multipart.commons.CommonsMultipartFile["fileItem"]->org.apache.commons.fileupload.disk.DiskFileItem["inputStream"])

-> 이거는 통신할 때 exchage 메소드에서 HttpHeaders 에 ContentType 을 "multipart/form-data" 로 세팅해주는 걸로 찾아서 찔러야 한다. (회사 내부 프레임워크 살펴볼 것)

 

혹시 그 이후에도 500에러가 났다? 그 에러가 MissingServletRequestPartException 즉, 저 multipartFile 을 분명 던졌는데 다른 서버에서 못받는다? 그러면 던질때 포멧을 다시 확인해보자..

// file 을 이렇게만 던졌다면
new ByteArrayResource(file.getBytes()) 

// fileName 을 오버라이딩해서 이렇게 던져보자. 이렇게 해야지 상대 서버에서 받아주는 것 같다.
new ByteArrayResource(file.getBytes()) {
	@Override
    public String getFilename() throws IllegalStateException {
    	return URLEncoder.encode(file.getName(), StandardCharsets.UTF_8);
    }
}
반응형

댓글