マルチパートファイルをファイルに変換する方法は?


90

マルチパートファイル(org.springframework.web.multipart.MultipartFile)をファイル(java.io.File)に変換する最良の方法を教えてもらえますか?

私の春のmvcWebプロジェクトでは、アップロードされたファイルをマルチパートファイルとして取得しています。ファイル(io)に変換する必要があるため、この画像保存サービス(Cloudinary)を呼び出すことができます。タイプは(File)のみです。

私はたくさんの検索をしましたが失敗しました。誰かが良い標準的な方法を知っているなら私に知らせてください。Thnx


5
この方法を使用できない理由はありますMultipartFile.transferTo()か?
fajarkoe 2014年

回答:


192

メソッドを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関数を使用しましたが、問題があると感じています。ローカルマシンのドライブに一時ファイルを保持します。
モレス2015年

@ロニー私は同じ問題を抱えています。回避策はありますか?
ハーフブラッドプリンス

1
org.apache.commons.io.FileUtils.deleteQuietly(convFile.getParentFile()); 、これにより、一時ファイル@Ronnie
kavinder

5
createNewFIle()ここでは無意味で無駄です。これでnew FileOutputStream()、(OSを介して)作成したファイルを削除すること、新しいファイルを作成することの両方を行う必要があります。
ローン侯爵2016

@Petros TsialiamanisJavaでのファイル変換サイズの制限はありますか。3GBのファイルを使用しているとしましょう。
Rohit 2018年

17

受け入れられた答えは正しいですが、画像をcloudinaryにアップロードしようとしているだけの場合は、より良い方法があります。

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

multipartFileはorg.springframework.web.multipart.MultipartFileです。


17

@PetrosTsialiamanisの投稿を少し修正する 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(...)


8

Apache CommonsIOライブラリと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()、(OSを介して)作成したファイルを削除すること、新しいファイルを作成することの両方を行う必要があります。
ローン侯爵2016

コメントありがとうございます。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(許可が拒否されました)
NavnathAdsul19年

1

インターフェイスのクラスMultipartFileCommonsMultipartFile。の場合、キャストすることでSpringのtempfileにアクセスできます。

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プロパティを@Configuration @EnableWebMvcクラスで0に設定できます。その後、アップロードされたすべてのファイルがディスクに保存されます。

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

2
createNewFIle()ここでは無意味で無駄です。これでnew FileOutputStream()、(OSを介して)作成したファイルを削除すること、新しいファイルを作成することの両方を行う必要があります。
ローン侯爵2016

@EJPはい、それは無意味でした、今私は編集中に行われたこの間違いを修正します。ただし、CommonsMultipartFileが10240バイト未満の場合、ファイルシステム内のファイルは作成されないため、createNewFIle()は無駄ではありません。したがって、任意の一意の名前(DiskFileItemの名前を使用)の新しいファイルをFSに作成する必要があります。
Alex78191 2016

@ Alex78191ディスクの小さなファイル(デフォルトでは<10240バイト)に暗黙的に保存するとはどういう意味ですか。とにかく制限を増やすことはありますか
Anand Tagore

@AnandTagoreつまり、MultipartFileの10240バイト未満はファイルシステムに保存されないため、ファイルは手動で作成する必要があります。
Alex78191 2016

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 2017

10240バイト未満のファイルでトリックを取り除くには、maxInMemorySizepropをに設定できます0
Alex78191 2017

@ Alex78191これを変更しましたが、うまくいきました。私はあなたのコードを使ってファイルを変換しました。そこで、メモリの制限を取り除くために、applicationcontext.xmlのプロパティを変更しました。そしてそれは動作します!!!
Anand Tagore

マルチパートファイルからファイルを作成するときは、メモリに保持する必要があります。そのためには、maxInMemorySizeを増やす必要があります。
アナンドタゴール2018年

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.