Problems uploading binaries with JavaScript FileReader API
New to javascript without understanding this, please help!
I am trying to use the Javascript FileReader API to read files to upload to the server. So far, it works fine for text files.
When I try to download binaries like image / .doc the files seem to be corrupted and won't open.
Using dojo on the client side and java on the server side, with dwr to handle remote method calls. Code:
Using html file input, so user can select multiple files at once:
<input type="file" id="fileInput" multiple>
And the javascript code that reads the content of the file:
uploadFiles: function(eve) {
var fileContent = null;
for(var i = 0; i < this.filesToBeUploaded.length; i++){
var reader = new FileReader();
reader.onload = (function(fileToBeUploaded) {
return function(e) {
fileContent = e.target.result;
// fileContent object contains the content of the read file
};
})(this.filesToBeUploaded[i]);
reader.readAsBinaryString(this.filesToBeUploaded[i]);
}
}
The fileContent object will be sent as a parameter to the java method that will write to the file.
public boolean uploadFile(String fileName, String fileContent) {
try {
File file = new File("/home/user/files/" + fileName);
FileOutputStream outputStream = new FileOutputStream(file);
outputStream.write(fileContent.getBytes());
outputStream.close();
} catch (FileNotFoundException ex) {
logger.error("Error uploading files: ", ex);
return false;
} catch (IOException ioe) {
logger.error("Error uploading files: ", ioe);
return false;
}
return true;
}
I have read several answers suggesting using xhr and servlets to achieve this.
Is there a way to use FileReader so that it can read any type of file (text, image, Excel, etc.)?
I tried using reader.readAsBinaryString()
and reader.readAsDataUrl()
(decoded the base64 fileContent before writing to the file) but they didn't seem to work.
PS: 1. Also, after trying reader.readAsArrayBuffer()
, the resulting object ArrayBuffer
shows some byteLength
but no content, and when this is passed to the server, all I can see is this {}
.
- This bit of code is only intended to work with newer versions of browsers.
source to share
Thanks to N.M. So it looks like ArrayBuffer objects cannot be used directly and the DataView must be created to use them. Following is the work -
uploadFiles: function(eve) {
var fileContent = null;
for(var i = 0; i < this.filesToBeUploaded.length; i++){
var reader = new FileReader();
reader.onload = (function(fileToBeUploaded) {
return function(e) {
fileContent = e.target.result;
var int8View = new Int8Array(fileContent);
// now int8View object has the content of the read file!
};
})(this.filesToBeUploaded[i]);
reader.readAsArrayBuffer(this.filesToBeUploaded[i]);
}
}
Refer to NM's comments on links to related pages.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
source to share
Example
<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.3/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.3/jquery-ui.js"></script>
</head>
<body>
<script>
function PreviewImage() {
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("uploadImage").files[0]);
oFReader.onload = function (oFREvent) {
var sizef = document.getElementById('uploadImage').files[0].size;
document.getElementById("uploadPreview").src = oFREvent.target.result;
document.getElementById("uploadImageValue").value = oFREvent.target.result;
};
};
jQuery(document).ready(function(){
$('#viewSource').click(function ()
{
var imgUrl = $('#uploadImageValue').val();
alert(imgUrl);
//here ajax
});
});
</script>
<div>
<input type="hidden" id="uploadImageValue" name="uploadImageValue" value="" />
<img id="uploadPreview" style="width: 150px; height: 150px;" /><br />
<input id="uploadImage" style="width:120px" type="file" size="10" accept="image/jpeg,image/gif, image/png" name="myPhoto" onchange="PreviewImage();" />
</div>
<a href="#" id="viewSource">Source file</a>
</body>
</html>
source to share