Czy ktoś może mi powiedzieć, jaki jest najlepszy sposób konwersji pliku wieloczęściowego (org.springframework.web.multipart.MultipartFile) do pliku (java.io.File)?
W moim wiosennym projekcie internetowym mvc otrzymuję przesyłany plik jako plik Multipart.Muszę przekonwertować go do pliku (io), dlatego mogę wywołać tę usługę przechowywania obrazów ( Cloudinary ) .Biorą one tylko typ (plik).
Zrobiłem tyle wyszukiwań, ale nie udało mi się. Jeśli ktoś zna dobry standardowy sposób, daj mi znać? Thnx
java
spring
spring-mvc
file-upload
cloudinary
Amila Iddamalgoda
źródło
źródło
MultipartFile.transferTo()
?Odpowiedzi:
Możesz pobrać zawartość a
MultipartFile
używającgetBytes
metody i możesz pisać do pliku za pomocą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()); } }
Możesz również skorzystać z metody transferTo :
public void multipartFileToFile( MultipartFile multipart, Path dir ) throws IOException { Path filepath = Paths.get(dir.toString(), multipart.getOriginalFilename()); multipart.transferTo(filepath); }
źródło
createNewFIle()
jest tu bezcelowy i marnotrawny. Teraz zobowiązujesz sięnew FileOutputStream()
(przez system operacyjny) zarówno do usunięcia tak utworzonego pliku, jak i do utworzenia nowego.Chociaż zaakceptowana odpowiedź jest prawidłowa, ale jeśli próbujesz tylko przesłać swój obraz do Cloudinary, jest lepszy sposób:
Gdzie multipartFile to Twój plik org.springframework.web.multipart.MultipartFile .
źródło
mała poprawka w poście @PetrosTsialiamanis,
new File( multipart.getOriginalFilename())
spowoduje to utworzenie pliku w lokalizacji serwera, gdzie czasami napotkasz problemy z uprawnieniami do zapisu dla użytkownika, nie zawsze jest możliwe nadanie uprawnień do zapisu każdemu użytkownikowi, który wykonuje akcję.System.getProperty("java.io.tmpdir")
utworzy katalog tymczasowy, w którym plik zostanie utworzony poprawnie. W ten sposób tworzysz folder tymczasowy, w którym zostanie utworzony plik, później możesz usunąć plik lub folder tymczasowy.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; }
umieść tę metodę w powszechnym narzędziu i używaj jej jak np.
Utility.multipartToFile(...)
źródło
Możesz także skorzystać z biblioteki Apache Commons IO i klasy FileUtils . Jeśli używasz mavena, możesz go załadować, korzystając z powyższej zależności.
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
Źródło zapisu MultipartFile na dysku.
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());
źródło
FileUtils.touch()
jest tu bezcelowy i marnotrawny. Teraz zobowiązujesz sięnew FileOutputStream()
(przez system operacyjny) zarówno do usunięcia tak utworzonego pliku, jak i do utworzenia nowego.MultipartFile.transferTo (File) jest fajny, ale nie zapomnij jednak wyczyścić pliku tymczasowego.
// 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();
Sprawdź komentarz Razzlero na temat File.deleteOnExit () wykonywanego przy wyjściu JVM (co może być niezwykle rzadkie) szczegóły poniżej.
źródło
deleteOnExit()
, będzie wyzwalane tylko po zakończeniu działania maszyny JVM, więc nie będzie wyzwalane podczas wyjątków. Z tego powodu należy zachować ostrożność podczas korzystaniadeleteOnExit()
z długotrwałych aplikacji, takich jak aplikacje serwerowe. W przypadku aplikacji serwerowych JVM rzadko kończy działanie. Musisz więc uważać, aby niedeleteOnExit()
spowodować wycieków pamięci. JVM musi śledzić wszystkie pliki, które musi usunąć przy wyjściu, które nie są czyszczone, ponieważ JVM nie kończy działania.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; }
źródło
Możesz uzyskać dostęp do pliku tymczasowego w Spring przez rzutowanie, jeśli klasa interfejsu
MultipartFile
toCommonsMultipartFile
.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; }
Aby pozbyć się sztuczki z plikami mniejszymi niż 10240 bajtów,
maxInMemorySize
właściwość można ustawić na 0 w@Configuration
@EnableWebMvc
klasie. Następnie wszystkie przesłane pliki zostaną zapisane na dysku.@Bean(name = "multipartResolver") public CommonsMultipartResolver createMultipartResolver() { CommonsMultipartResolver resolver = new CommonsMultipartResolver(); resolver.setDefaultEncoding("utf-8"); resolver.setMaxInMemorySize(0); return resolver; }
źródło
createNewFIle()
jest tu bezcelowy i marnotrawny. Teraz zobowiązujesz sięnew FileOutputStream()
(przez system operacyjny) zarówno do usunięcia tak utworzonego pliku, jak i do utworzenia nowego.Odpowiedź Alex78191 zadziałała dla mnie.
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; }
Aby przesłać pliki o rozmiarze większym niż 10240 bajtów, zmień maxInMemorySize w multipartResolver na 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>
źródło
maxInMemorySize
nie ma nic wspólnego z ograniczeniem rozmiaru przesyłanych plików. Rozmiar przesyłanego pliku jest ustawiany przezmaxUploadSize
usługę.maxInMemorySize
można ustawić właściwość0
.jeśli nie chcesz używać MultipartFile.transferTo (). Możesz napisać plik w ten sposób
val dir = File(filePackagePath) if (!dir.exists()) dir.mkdirs() val file = File("$filePackagePath${multipartFile.originalFilename}").apply { createNewFile() } FileOutputStream(file).use { it.write(multipartFile.bytes) }
źródło