Home > Blockchain >  File has been moved, can not be read again (Spring mvc)
File has been moved, can not be read again (Spring mvc)

Time:10-03

I am using spring MVC where through API I am uploading zip file using MultipartFile. In backend I have to convert uploaded zip file into InputStream for further processing. But my code is giving error intermittently " File has been moved, can not be read again ".

here is the code snippet :

            File temp = null;
            InputStream stream = null;
            try {
                InputStream initialStream = inputFile.getInputStream();
                byte[] buffer = new byte[initialStream.available()];
                initialStream.read(buffer);
                temp = File.createTempFile("upload", null);
                try (OutputStream outStream = new FileOutputStream(temp)) {
                    outStream.write(buffer);
                }
                ZipFile zipFile = new ZipFile(temp);
                stream = zipFile.getInputStream(zipFile.getEntries().nextElement());
            } catch (Exception e) {
                log.error("Exception occurred while processing zip file "   e.getMessage());
                throw e;
            } finally {
                if (temp != null)
                    temp.delete();
            }
            return stream;

Here inputFile is MultipartFile.

Could you please suggest what is wrong here?

CodePudding user response:

Your code is returning an input stream from a file that you have deleted - last line is temp.delete().

ZipInputStream has a small internal buffer for decoding, so that may explain why some read calls work after the delete, but it will not be possible to continue reading from a file that you deleted, hence the exception.

I would not recommend doing any work with files or multipart streams using direct transfer to byte[] as you risk OutOfMemoryException. However in your case where you are happy to have byte[] for the ZIP and you read the first entry of the ZIP file (and are ignoring other entries) then you could try extracting the first entry as InputStream without writing to a file as follows:

// Read a zip input stream from a zip stored in byte[]:
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(buffer));
// Select first entry from ZIP
ZipEntry entry = zis.getNextEntry();

// You should be able to read the entry from zis directly,
// if this is text file you could test with:
//    zis.transferTo(System.out);

return zis;

You should ensure that you close the stream after use.

CodePudding user response:

Potential issues I can see in your code:

  1. temp file is used as zip file, yet you delete the temp file prior to returning. How can you use the zip file as file stream if you have deleted it?

  2. Do you support concurrent uploads? If yes, then you have concurrent resource access problem. Multiple calls to create temp file: "upload" and process it. Why don't you create a different filename e.g. with datetime suffix random number suffix.

  • Related