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


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.