Bagaimana cara mengonversi file multipart ke File?

91

Adakah yang bisa memberi tahu saya apa cara terbaik untuk mengonversi file multi bagian (org.springframework.web.multipart.MultipartFile) ke File (java.io.File)?

Dalam proyek web mvc musim semi saya, saya mendapatkan file yang diunggah sebagai file Multipart. Saya harus mengubahnya menjadi File (io), oleh karena itu saya dapat memanggil layanan penyimpanan gambar ini ( Cloudinary ). Mereka hanya mengambil jenis (File).

Saya telah melakukan begitu banyak pencarian tetapi gagal. Jika ada yang tahu cara standar yang baik, beri tahu saya? Thnx

Amila Iddamalgoda
sumber
5
Apakah ada sesuatu yang menghalangi Anda untuk menggunakan metode ini MultipartFile.transferTo()?
fajarkoe

Jawaban:

193

Anda bisa mendapatkan konten a MultipartFiledengan menggunakan getBytesmetode ini dan Anda bisa menulis ke file menggunakan 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());
    }
}

Anda juga dapat menggunakan metode transferTo :

public void multipartFileToFile(
    MultipartFile multipart, 
    Path dir
) throws IOException {
    Path filepath = Paths.get(dir.toString(), multipart.getOriginalFilename());
    multipart.transferTo(filepath);
}
Petros Tsialiamanis
sumber
7
Saya menggunakan fungsi transferTo tetapi saya merasa ada masalah. seperti Itu membuat file temp untuk drive untuk mesin lokal.
Morez
@Ronnie Saya mengalami masalah yang sama. Apakah Anda sudah menemukan solusi?
Half Blood Prince
1
org.apache.commons.io.FileUtils.deleteQuietly (convFile.getParentFile ()); , ini harus menghapus file temp @Ronnie
kavinder
5
createNewFIle()tidak ada gunanya dan sia-sia di sini. Anda sekarang mewajibkan new FileOutputStream()(melalui OS) untuk menghapus file yang sudah dibuat dan membuat yang baru.
Marquis dari Lorne
@Petros Tsialiamanis Apakah ada batas ukuran konversi File di Jawa. Katakanlah saya menggunakan file 3GB.
Rohit
17

Meskipun jawaban yang diterima benar tetapi jika Anda hanya mencoba mengunggah gambar Anda ke cloudinary, ada cara yang lebih baik:

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

Di mana multipartFile adalah org.springframework.web.multipart.MultipartFile Anda .

Heisenberg
sumber
17

koreksi kecil pada posting @PetrosTsialiamanis, new File( multipart.getOriginalFilename())ini akan membuat file di lokasi server di mana terkadang Anda akan menghadapi masalah izin menulis untuk pengguna, tidak selalu memungkinkan untuk memberikan izin tulis kepada setiap pengguna yang melakukan tindakan. System.getProperty("java.io.tmpdir")akan membuat direktori temp di mana file Anda akan dibuat dengan benar. Dengan cara ini Anda membuat folder temp, tempat file dibuat, nanti Anda dapat menghapus file atau folder temp.

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;
}

letakkan metode ini di utilitas umum Anda dan gunakan seperti untuk misalnya. Utility.multipartToFile(...)

Swadeshi
sumber
8

Anda juga dapat menggunakan pustaka Apache Commons IO dan kelas FileUtils . Jika Anda menggunakan maven, Anda dapat memuatnya menggunakan dependensi di atas.

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

Sumber untuk MultipartFile simpan ke disk.

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());
George Siggouroglou
sumber
FileUtils.touch()tidak ada gunanya dan sia-sia di sini. Anda sekarang mewajibkan new FileOutputStream()(melalui OS) untuk menghapus file yang sudah dibuat dan membuat yang baru.
Marquis dari Lorne
Terima kasih atas komentarmu. Saya memeriksa sumber metode FileUtils.writeByteArrayToFile. Saya pikir metode ini tidak membuat ulang file jika ada (versi 2.4). Objek multipartFile menyertakan byte dari file yang diunggah yang ingin kita simpan di suatu tempat di sistem file. Tujuan saya adalah menyimpan byte ini ke lokasi pilihan. Satu-satunya alasan saya menyimpan metode FileUtils.touch adalah untuk memperjelas bahwa ini adalah file baru. FileUtils.writeByteArrayToFile membuat file (dan jalur lengkap) jika tidak ada sehingga FileUtils.touch tidak diperlukan.
George Siggouroglou
7

MultipartFile.transferTo (File) bagus, tapi jangan lupa untuk membersihkan file temp.

// 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();

Lihat komentar Razzlero tentang File.deleteOnExit () yang dieksekusi setelah keluar dari JVM (yang mungkin sangat jarang) detail di bawah ini.

andrej
sumber
2
deleteOnExit(), ini hanya akan terpicu saat JVM dihentikan, jadi tidak akan terpicu selama pengecualian. Karena itu, Anda perlu berhati-hati menggunakan deleteOnExit()aplikasi yang berjalan lama seperti aplikasi server. Untuk aplikasi server, JVM jarang keluar. Jadi, Anda perlu berhati-hati agar tidak deleteOnExit()menyebabkan kebocoran memori. JVM perlu melacak semua file yang perlu dihapus saat keluar yang tidak dihapus karena JVM tidak berhenti.
Razzlero
@Razzlero terima kasih telah menunjukkan bahwa itu menghapus file hanya setelah keluar dari JVM. Namun ini bukan kebocoran memori, ini berfungsi seperti yang dirancang.
andrej
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;
    }
sachintha hewawasam
sumber
memberikan pengecualian ini java.io.FileNotFoundException: multipdf.pdf (Izin ditolak)
Navnath Adsul
1

Anda dapat mengakses tempfile di Spring dengan mentransmisikan jika kelas antarmukanya MultipartFileadalah 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;
}

Untuk menghilangkan trik dengan file kurang dari 10240 byte maxInMemorySizeproperti dapat diatur ke 0 di @Configuration @EnableWebMvckelas. Setelah itu, semua file yang diunggah akan disimpan di disk.

@Bean(name = "multipartResolver")
    public CommonsMultipartResolver createMultipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding("utf-8");
        resolver.setMaxInMemorySize(0);
        return resolver;
    }
Alex78191
sumber
2
createNewFIle()tidak ada gunanya dan sia-sia di sini. Anda sekarang mewajibkan new FileOutputStream()(melalui OS) untuk menghapus file yang sudah dibuat dan membuat yang baru.
Marquis dari Lorne
@EJP ya, tidak ada gunanya, sekarang saya memperbaiki kesalahan yang dibuat saat mengedit. Tetapi createNewFIle () tidak boros, karena jika CommonsMultipartFile kurang dari 10240 byte, file dalam sistem file tidak dibuat. Jadi file baru dengan nama unik apa pun (saya menggunakan nama DiskFileItem) harus dibuat di FS.
Alex78191
@ Alex78191 Apa yang Anda maksud dengan menyimpan file kecil secara implisit di disk (secara default <10240 byte). Apakah ada cara untuk meningkatkan batas
Anand Tagore
@AnandTagore Maksud saya MultipartFile kurang dari 10240 byte tidak disimpan dalam sistem file, jadi File harus dibuat secara manual.
Alex78191
0

Jawaban oleh Alex78191 berhasil untuk saya.

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;
}

Untuk mengunggah file yang berukuran lebih dari 10240 byte, harap ubah maxInMemorySize di multipartResolver menjadi 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>
Anand Tagore
sumber
maxInMemorySizetidak ada hubungannya dengan batasan ukuran upload file. Ukuran unggahan file ditentukan oleh maxUploadSizeproperti.
Alex78191
Untuk menghilangkan trik dengan file kurang dari 10240 byte maxInMemorySizeprop dapat diatur ke 0.
Alex78191
@ Alex78191 Saya telah mengubah ini dan itu berhasil untuk saya. Saya telah menggunakan kode Anda untuk mengonversi file. Jadi saya mengubah properti di applicationcontext.xml untuk menghilangkan batasan memori. Dan itu berhasil !!!
Anand Tagore
Saat membuat file dari file multipart, itu harus disimpan di memori. Jadi untuk itu saya harus meningkatkan maxInMemorySize.
Anand Tagore
0

jika Anda tidak ingin menggunakan MultipartFile.transferTo (). Anda dapat menulis file seperti ini

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

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

    FileOutputStream(file).use {
        it.write(multipartFile.bytes)
    }
Artem Botnev
sumber