I am using the Tomahawk inputFileUpload component to allow users to upload files to a server. I have implemented a "soft" file size limit by checking the size of the file after it has been uploaded and displaying an error if it is too large. However I would also like a larger "hard" limit, where uploading immediately stops once it has passed the limit. For example if the hard limit is 500MB and the user attempts to upload a 2GB file, uploading will immediately stop once 500MB has been uploaded and an error is displayed.
I had hoped that using the MyFaces ExtensionsFilter and setting uploadMaxFileSize would fix the problem, but the file is completely uploaded before the SizeLimitExceededException is thrown.
Is it possible to do this? Ideally I'd still be able to use Tomahawk but any other solution would be good.
The web server can't abort a HTTP request halfway and then return a HTTP response. The entire HTTP request has to be consumed fully until the last bit before a HTTP response can ever be returned. That's the nature of HTTP and TCP/IP. There's nothing you can do against it with a server side programming language.
Note that the Tomahawk file upload size limit already takes care that the server's memory/disk space won't be polluted with the entire uploaded file whenever the size limit has been hit.
Your best bet is to validate the file length in JavaScript before the upload takes place. This is supported in browsers supporting HTML5 File
API. The current versions of Firefox, Chrome, Safari, Opera and Android support it. IE9 doesn't support it yet, it'll be in the future IE10.
<t:inputFileUpload ... onchange="checkFileSize(this)" />
with something like this
function checkFileSize(inputFile) {
var max = 500 * 1024 * 1024; // 500MB
if (inputFile.files && inputFile.files[0].size > max) {
alert("File too large."); // Do your thing to handle the error.
inputFile.value = null; // Clears the field.
}
}
Try this:
<div>
<p:fileUpload id="fileUpload" name="fileUpload" value="#{controller.file}" mode="simple" rendered="true"/>
<input type="button" value="Try it" onclick="checkFileSize('fileUpload')" />
</div>
When user click in the button "Try it", checkFileSize() function is called and the fileUpload primefaces component is validated. If file size is greater than 500MB the file not is uploaded.
<script>
// <![CDATA[
function checkFileSize(name) {
var max = 500 * 1024 * 1024; // 500MB
var inputFile = document.getElementsByName(name)[0];
var inputFiles = inputFile.files;
if (inputFiles.lenght > 0 && inputFiles[0].size > max) {
alert("File too large."); // Do your thing to handle the error.
inputFile.value = null; // Clears the field.
}
}
// ]]>
</script>
The checkFileSize() logic is based on the BalusC answered above.
Versions tested:
primefaces 3.5
jsf 2.1