I'm getting InputStream of attached file by web service. When the user attaches an empty file, the input stream is not empty, but contains the header of the file (taht can be image, video, zip and others). When I read inputStream.available() I get 11 - the size of the header. I believe that for every type of file there is different header size, so I can't rely on that. I can't also read the file by ImageIO.read, because the file is not have to be an image file. Is there any way to know if the data in the input stream is only an header?
Those headers must be specified somewhere. That specification should tell you whether they're binary or text, and their structure. If the specification is even remotely sane, there must be a way to tell when you've reached the end of the headers. Ideally, the headers should also provide a direct way to tell whether the file is empty (such as its size).
Read from the input stream, parse the headers and decide from there (if you run out of headers to parse and there's more data, you have a non-empty file).
The "for dummies" solution would be to read the InputStream until you hit either non-headers or the end of file. You can reset
it if you want to read it "for real".
A smarter alternative would be to check your HTTPServletRequest.getContentLength() before even grabbing the InputStream. But that assumes the length is enough to tell empty headers from significant content.
Another practical solution: read and buffer the stream inside your application. Then check the buffer. If it's invalid, leave it for gc, otherwise, create a ByteArrayInputStream with that buffer and hand this (new) stream over to the correct file handler. It will not kill performance.
Quick draft:
public void handleIncomingStream(InputStream in) throws Exception /* KISS */{
byte[] buffer = getBytes(in);
if (containsJustHeader(buffer)) {
return;
}
InputStream internal = new ByteArrayInputStream(buffer);
StreamHandler handler = determineAppropriateStreamHandler(buffer);
handler.process(internal);
internal.close();
}
Note that I invented the StreamHandler interface... With this example you'd implement stream handlers for the various filetypes, like image, text and so on. Note as well, that the exception handling in this example is the worst case, that I choose only to keep the example simple (KISS)
Edit
Quick draft without handler
public void handleIncomingStream(InputStream in) throws Exception /* KISS */{
byte[] buffer = getBytes(in);
if (containsJustHeader(buffer)) {
throw new UnexpectedEmptyFileException(createErrorMessage(buffer));
}
InputStream internal = new ByteArrayInputStream(buffer);
copyFile(internal);
internal.close();
}
private boolean containsJustHeader(buffer) {
return buffer.length < MAGIC_PLAIN_HEADER_SIZE; // 11 bytes?
}