86

I have a method which expects the one of the input variable to be of java.io.File type but what I get is only InputStream. Also, I cannot change the signature of the method.

How can I convert the InputStream into File type with out actually writing the file on to the filesystem?

Renato Back
  • 706
  • 1
  • 10
  • 21
Ram
  • 3,034
  • 11
  • 38
  • 46

4 Answers4

129

Something like this should work. Note that for simplicity, I've used a Java 7 feature (try block with closeable resource), and IOUtils from Apache commons-io. If you can't use those it'll be a little longer, but the same idea.

import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class StreamUtil {

    public static final String PREFIX = "stream2file";
    public static final String SUFFIX = ".tmp";

    public static File stream2file (InputStream in) throws IOException {
        final File tempFile = File.createTempFile(PREFIX, SUFFIX);
        tempFile.deleteOnExit();
        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            IOUtils.copy(in, out);
        }
        return tempFile;
    }

}
cobbzilla
  • 1,920
  • 1
  • 16
  • 17
  • 8
    Isn't createTempFile actually does write a real file, that you can see in the file-system? – android developer Apr 11 '16 at 13:57
  • you are technically correct. using the code above, the temp file will exist until the program exits or it is deleted by the program. – cobbzilla Apr 21 '16 at 02:07
  • The docs of deleteOnExit say you shouldn't rely on it to work (and I think it actually doesn't even do anything) : http://developer.android.com/reference/java/io/File.html#deleteOnExit() . In addition, if you know how to stream the audio into playing, without any file, please write about it here: http://stackoverflow.com/q/36552381/878126 – android developer Apr 21 '16 at 05:24
  • 4
    Generally speaking, I prefer for the application to delete the temp file when it makes sense to do so. I use `deleteOnExit` as an extra sanity-check, never relying on it unconditionally. I know that in certain situations (`kill -9` the JVM, for example) the shutdown hooks that perform the deletion will never get called. – cobbzilla Jul 29 '16 at 00:15
  • If you're using this on Android, add ```implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'``` to gradle. – LordParsley Mar 20 '18 at 11:01
  • If you are using Spring framework, you could use its `FileCopyUtils.copy(..)` instead of `IOUtils.copy(..)` – Afshar Jan 09 '21 at 08:57
  • `IOUtils` is deprecated – abdulwasey20 Feb 25 '21 at 07:59
31

You can't. The input stream is just a generic stream of data and there is no guarantee that it actually originates from a File. If someone created an InputStream from reading a web service or just converted a String into an InputStream, there would be no way to link this to a file. So the only thing you can do is actually write data from the stream to a temporary file (e.g. using the File.createTempFile method) and feed this file into your method.

Jan Thomä
  • 13,296
  • 6
  • 55
  • 83
  • 8
    Indeed, the [`File#createTempFile()`](http://download.oracle.com/javase/6/docs/api/java/io/File.html#createTempFile%28java.lang.String,%20java.lang.String%29) is really your best bet. – BalusC Nov 30 '10 at 18:23
  • 8
    Also see [`File#deleteOnExit()`](http://download.oracle.com/javase/6/docs/api/java/io/File.html#deleteOnExit%28%29), which causes the JVM to attempt to delete the file automatically when the JVM exits. Of course it's best to delete the temp file manually and immediately, once you know the file is no longer needed and no longer in use. But in an imperfect world sometimes imperfect solutions are necessary. – Mike Clark Nov 30 '10 at 18:43
0

If you want to use the MultiPartFile in testing like getting a document from the resource folder -- you can use this.

import org.springframework.mock.web.MockMultipartFile;


ClassLoader classLoader = SomeClass.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(BASE_DIR + fileName);
MockMultipartFile("file", "NameOfTheFile", "multipart/form-data", inputStream);
Braden Borman
  • 309
  • 1
  • 8
0

If anyone just wanted to read bytes from InputStream, for that job you don't have to create file and then read it from source.

This can be done with below example, and key method here are "readAllBytes", which is introduce with JDK 9 in System class.

Example:

URL url = new URL("http://www.google.com");
        InputStream io = url.openStream();
        System.setIn(io);
        byte[] bytes = System.in.readAllBytes();
        String str = new String(bytes);
        System.out.println(str);
Simmant
  • 1,477
  • 25
  • 39