vaadin/vaadin-upload

FileBuffer getInputStream() is closed

Kai-W opened this issue · 10 comments

Kai-W commented

The Inputsream returned by the FileBuffer cant be accessed because it's closed.

        FileBuffer buffer = new FileBuffer();
        Upload upload = new Upload(buffer);
        upload.addSucceededListener(event -> {
            System.out.println(buffer.getFileDescriptor().valid()); //false 
            try {
                buffer.getInputStream().read(); // java.io.IOException: Stream Closed
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

The FileDescriptor is part of the Outputstream.
Javadoc of FileDescriptor:
Instances of the file descriptor class serve as an opaque handle to the underlying machine-specific structure representing an open file, an open socket, or another source or sink of bytes.
So the Descriptor gets invalidated by closing the Outputstream.
return new FileInputStream( ((FileOutputStream) file.getOutputBuffer()).getFD());
Creates a new Inputstream of a closed Fiel Descriptor.

is the bug has already been solved?

Im still getting the same error..

upload.addSucceededListener(event -> {
try {
System.out.println("result: "+convertStreamToString(fileBuffer.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(MembersAccount.class.getName()).log(Level.SEVERE, null, ex);
}
});

String convertStreamToString(InputStream is) throws IOException{
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
// StandardCharsets.UTF_8.name() > JDK 7
return result.toString("UTF-8");
}


upload.addSucceededListener(event -> { try { String result = IOUtils.toString(fileBuffer.getInputStream(), StandardCharsets.UTF_8); System.out.print("result: "+result); } catch (IOException ex) { Logger.getLogger(MembersAccount.class.getName()).log(Level.SEVERE, null, ex); } });

Kai-W commented

The issue is still open.
As Workaround I used the MemoryBuffer / MultiFileMemoryBuffer as reciever.

The issue is still open.
As Workaround I used the MemoryBuffer / MultiFileMemoryBuffer as reciever.

I've noticed that upload events disable System.out.print/ln() method

You could also use your own simple implementation of (Multi)FileReceiver. For example:

public class MultiFileBuffer implements MultiFileReceiver, HasLogger {
	private static final Logger LOGGER = LoggerFactory.getLogger(MultiFileBuffer.class);

	private Map<String, FileData> files = new HashMap<>();

	private Map<String, String> tempFileNames = new HashMap<>();

	private FileOutputStream createFileOutputStream(String fileName) {
		try {
			return new FileOutputStream(createFile(fileName));
		} catch (IOException e) {
			LOGGER.warn("Failed to create file output stream for: '" + fileName + "'", e);
		}
		return null;
	}

	private File createFile(String fileName) throws IOException {
		String tempFileName = "upload_tmpfile_" + fileName + "_"
				+ System.currentTimeMillis();

		File tempFile = File.createTempFile(tempFileName, null);
		tempFileNames.put(fileName, tempFile.getPath());

		return tempFile;
	}

	@Override
	public OutputStream receiveUpload(String fileName, String MIMEType) {
		FileOutputStream outputBuffer = createFileOutputStream(fileName);
		files.put(fileName, new FileData(fileName, MIMEType, outputBuffer));

		return outputBuffer;
	}

	public Set<String> getFiles() {
		return files.keySet();
	}

	public FileData getFileData(String fileName) {
		return files.get(fileName);
	}


	public InputStream getInputStream(String fileName) {
		if (tempFileNames.containsKey(fileName)) {
			try {
				return new FileInputStream(tempFileNames.get(fileName));
			} catch (IOException e) {
				LOGGER.warn("Failed to create InputStream for: '" + fileName + "'", e);
			}
		}
		return new ByteArrayInputStream(new byte[0]);
	}

}
Braus commented

I also encountered this bug and asked on the forum:
https://vaadin.com/forum/thread/17784824

Unfortunately, it's still broken in 14.0.0.rc7.

Still in 14.0.10, so FileBuffer.getInputStream() is virtually unusable and you have to write your own FileBuffer and create FileInputStream from path to tmp file or from tmp File object

Our devs tell me that this issue also affects us and has stolen quite some time already. (Until we found this existing bug report)

Please fix, this is still not resolved with Vaadin 14.4.0...