멀티 파트 파일을 파일로 변환하는 방법?


92

아무도 멀티 파트 파일 (org.springframework.web.multipart.MultipartFile)을 파일 (java.io.File)로 변환하는 가장 좋은 방법이 무엇인지 말해 줄 수 있습니까?

내 봄 mvc 웹 프로젝트에서 나는 Multipart 파일로 업로드 된 파일을 얻고 있습니다. 파일 (io)로 변환해야 하므로이 이미지 저장 서비스 ( Cloudinary )를 호출 할 수 있습니다 .

너무 많은 검색을했지만 실패했습니다. 좋은 표준 방법을 아는 사람이 있으면 알려주세요. Thnx


5
방법을 사용하지 못하게하는 것이 MultipartFile.transferTo()있습니까?
— fajarkoe

답변:


194

메소드 MultipartFile를 사용하여 의 내용을 가져올 수 있으며 다음 을 사용 getBytes하여 파일에 쓸 수 있습니다 Files.newOutputStream().

public void write(MultipartFile file, Path dir) {
    Path filepath = Paths.get(dir.toString(), file.getOriginalFilename());

    try (OutputStream os = Files.newOutputStream(filepath)) {
        os.write(file.getBytes());
    }
}

transferTo 메서드를 사용할 수도 있습니다 .

public void multipartFileToFile(
    MultipartFile multipart, 
    Path dir
) throws IOException {
    Path filepath = Paths.get(dir.toString(), multipart.getOriginalFilename());
    multipart.transferTo(filepath);
}

7
transferTo Function을 사용했지만 문제가 있다고 생각합니다. 그것은 로컬 머신에 대한 임시 파일을 유지합니다.
— Morez

@Ronnie 나는 같은 문제가 있습니다. 해결 방법을 찾았습니까?
— Half Blood Prince

1
org.apache.commons.io.FileUtils.deleteQuietly (convFile.getParentFile ()); 이것은 임시 파일 @Ronnie 삭제해야
— kavinder

5
createNewFIle()여기서는 무의미하고 낭비 적입니다. 이제 의무화되어 new FileOutputStream()있으므로 생성 된 파일을 삭제 모두 (운영 체제를 통해) 와 새로 만듭니다.
— 론의 후작

@Petros Tsialiamanis Java에서 파일 변환 크기 제한이 있습니까? 3GB의 파일을 사용하고 있다고 가정 해 보겠습니다.
— Rohit

18

@PetrosTsialiamanis post에 대한 작은 수정, new File( multipart.getOriginalFilename())이것은 언젠가 사용자에 대한 쓰기 권한 문제에 직면하게 될 서버 위치에 파일을 생성합니다. 작업을 수행하는 모든 사용자에게 항상 쓰기 권한을 부여 할 수있는 것은 아닙니다. System.getProperty("java.io.tmpdir")파일이 제대로 생성 될 임시 디렉토리를 생성합니다. 이렇게하면 파일이 생성되는 임시 폴더를 만들고 나중에 파일 또는 임시 폴더를 삭제할 수 있습니다.

public  static File multipartToFile(MultipartFile multipart, String fileName) throws IllegalStateException, IOException {
    File convFile = new File(System.getProperty("java.io.tmpdir")+"/"+fileName);
    multipart.transferTo(convFile);
    return convFile;
}

이 방법을 일반적인 유틸리티에 넣고 예를 들어처럼 사용하십시오. Utility.multipartToFile(...)


17

받아 들여지는 대답은 정확하지만 이미지를 cloudinary에 업로드하려는 경우 더 좋은 방법이 있습니다.

Map upload = cloudinary.uploader().upload(multipartFile.getBytes(), ObjectUtils.emptyMap());

multipartFile은 org.springframework.web.multipart.MultipartFile 입니다.


8

Apache Commons IO 라이브러리 및 FileUtils 클래스를 사용할 수도 있습니다 . maven을 사용하는 경우 위의 종속성을 사용하여로드 할 수 있습니다.

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

MultipartFile의 소스는 디스크에 저장됩니다.

File file = new File(directory, filename);

// Create the file using the touch method of the FileUtils class.
// FileUtils.touch(file);

// Write bytes from the multipart file to disk.
FileUtils.writeByteArrayToFile(file, multipartFile.getBytes());

FileUtils.touch()여기서는 무의미하고 낭비 적입니다. 이제 의무화되어 new FileOutputStream()있으므로 생성 된 파일을 삭제 모두 (운영 체제를 통해) 와 새로 만듭니다.
— 론의 후작

당신의 의견에 감사드립니다. FileUtils.writeByteArrayToFile 메소드의 소스를 확인했습니다. 이 방법은 파일이 존재하는 경우 파일을 다시 생성하지 않는다고 생각합니다 (버전 2.4). multipartFile 객체는 파일 시스템 어딘가에 저장하려는 업로드 된 파일의 바이트를 포함합니다. 내 목적은이 바이트를 선호하는 위치에 저장하는 것입니다. FileUtils.touch 메서드를 유지하는 유일한 이유는 이것이 새 파일임을 분명히하기 위해서입니다. FileUtils.writeByteArrayToFile은 파일이없는 경우 파일 (및 전체 경로)을 생성하므로 FileUtils.touch가 필요하지 않습니다.
— George Siggouroglou 2016 년

7

MultipartFile.transferTo (File)은 좋지만 결국 임시 파일을 정리하는 것을 잊지 마십시오.

// ask JVM to ask operating system to create temp file
File tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_POSTFIX);

// ask JVM to delete it upon JVM exit if you forgot / can't delete due exception
tempFile.deleteOnExit();

// transfer MultipartFile to File
multipartFile.transferTo(tempFile);

// do business logic here
result = businessLogic(tempFile);

// tidy up
tempFile.delete();

아래에서 JVM 종료시 실행되는 File.deleteOnExit ()에 대한 Razzlero의 주석 (극히 드물지만) 세부 정보를 확인하십시오.


2
deleteOnExit(), JVM이 종료 될 때만 트리거되므로 예외 중에 트리거되지 않습니다. 이 때문에 deleteOnExit()서버 응용 프로그램과 같이 오래 실행되는 응용 프로그램에서 사용 하는 데 주의해야 합니다. 서버 애플리케이션의 경우 JVM이 거의 종료되지 않습니다. 따라서 deleteOnExit()메모리 누수 가 발생하지 않도록주의해야합니다 . JVM은 JVM이 종료되지 않기 때문에 지워지지 않은 종료시 삭제해야하는 모든 파일을 추적해야합니다.
— Razzlero

@Razzlero는 JVM 종료시에만 파일을 삭제한다고 지적 해 주셔서 감사합니다. 그러나 메모리 누수가 아니라 설계된대로 작동합니다.
— 안드레이

5
  private File convertMultiPartToFile(MultipartFile file ) throws IOException
    {
        File convFile = new File( file.getOriginalFilename() );
        FileOutputStream fos = new FileOutputStream( convFile );
        fos.write( file.getBytes() );
        fos.close();
        return convFile;
    }

이 예외를 제공하는 java.io.FileNotFoundException : multipdf.pdf (허가 거부 됨)
— Navnath Adsul

1

당신은 인터페이스의 클래스가있는 경우 캐스팅에 의해 봄에 임시 파일에 액세스 할 수 MultipartFile있습니다 CommonsMultipartFile.

public File getTempFile(MultipartFile multipartFile)
{
    CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartFile;
    FileItem fileItem = commonsMultipartFile.getFileItem();
    DiskFileItem diskFileItem = (DiskFileItem) fileItem;
    String absPath = diskFileItem.getStoreLocation().getAbsolutePath();
    File file = new File(absPath);

    //trick to implicitly save on disk small files (<10240 bytes by default)
    if (!file.exists()) {
        file.createNewFile();
        multipartFile.transferTo(file);
    }

    return file;
}

10240 바이트 미만의 파일로 트릭을 제거하려면 클래스 maxInMemorySize에서 속성을 0으로 설정할 수 있습니다 @Configuration @EnableWebMvc. 그 후에 업로드 된 모든 파일은 디스크에 저장됩니다.

@Bean(name = "multipartResolver")
    public CommonsMultipartResolver createMultipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding("utf-8");
        resolver.setMaxInMemorySize(0);
        return resolver;
    }

2
createNewFIle()여기서는 무의미하고 낭비 적입니다. 이제 의무화되어 new FileOutputStream()있으므로 생성 된 파일을 삭제 모두 (운영 체제를 통해) 와 새로 만듭니다.
— Marquis of Lorne

@EJP 예, 무의미했습니다. 이제 편집하는 동안이 실수를 수정합니다. 그러나 createNewFIle ()은 낭비되지 않습니다. CommonsMultipartFile이 10240 바이트 미만이면 파일 시스템의 파일이 생성되지 않기 때문입니다. 따라서 고유 한 이름 (DiskFileItem의 이름을 사용)을 가진 새 파일이 FS에 생성되어야합니다.
— Alex78191

@ Alex78191 암시 적으로 디스크에 작은 파일을 저장한다는 의미입니다 (기본적으로 <10240 바이트). 한도 증가 어쨌든 거기
— 아난드 타고르

@AnandTagore MultipartFile의 10240 바이트 미만은 파일 시스템에 저장되지 않으므로 파일을 수동으로 만들어야합니다.
— Alex78191

0

Alex78191의 답변이 저에게 효과적이었습니다.

public File getTempFile(MultipartFile multipartFile)
{

CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile) multipartFile;
FileItem fileItem = commonsMultipartFile.getFileItem();
DiskFileItem diskFileItem = (DiskFileItem) fileItem;
String absPath = diskFileItem.getStoreLocation().getAbsolutePath();
File file = new File(absPath);

//trick to implicitly save on disk small files (<10240 bytes by default)

if (!file.exists()) {
    file.createNewFile();
    multipartFile.transferTo(file);
}

return file;
}

크기가 10240 바이트보다 큰 파일을 업로드하려면 multipartResolver의 maxInMemorySize를 1MB로 변경하십시오.

<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- setting maximum upload size t 20MB -->
<property name="maxUploadSize" value="20971520" />
<!-- max size of file in memory (in bytes) -->
<property name="maxInMemorySize" value="1048576" />
<!-- 1MB --> </bean>

maxInMemorySize파일 업로드 크기 제한과 관련이 없습니다. 파일 업로드 크기는 maxUploadSize속성에 의해 설정됩니다 .
— Alex78191

10240 바이트 미만의 파일로 트릭을 제거하려면 maxInMemorySizeprop을 0.
— Alex78191

@ Alex78191 나는 이것을 변경했고 그것은 나를 위해 일했습니다. 파일을 변환하기 위해 코드를 사용했습니다. 그래서 메모리 제한을 없애기 위해 applicationcontext.xml의 속성을 변경했습니다. 그리고 작동합니다 !!!
— Anand Tagore

멀티 파트 파일에서 파일을 생성하는 동안 메모리에 보관해야합니다. 그래서 나는 maxInMemorySize를 늘려야합니다.
— Anand Tagore

0

MultipartFile.transferTo ()를 사용하지 않으려면. 다음과 같이 파일을 작성할 수 있습니다.

    val dir = File(filePackagePath)
    if (!dir.exists()) dir.mkdirs()

    val file = File("$filePackagePath${multipartFile.originalFilename}").apply {
        createNewFile()
    }

    FileOutputStream(file).use {
        it.write(multipartFile.bytes)
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.