Trouble uploading binary files using JavaScript FileReader API - javascript

New to javascript, having trouble figuring this out, help!
I am trying to use the Javascript FileReader API to read files to upload to a server. So far, it works great for text files.
When I try to upload binary files, such as image/.doc, the files seem to be corrupted, and do not open.
Using dojo on the client side, and java on the server side, with dwr to handle remote method calls. Code :
Using a html file input, so a user can select multiple files to upload at once :
<input type="file" id="fileInput" multiple>
And the javascript code which reads the file content:
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 a java method, which will write 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 some answers suggesting the use of xhr and servlets to achieve this.
Is there a way to use FileReader, so that it can read files of any type (text, image, excel etc.) ?
I have tried using reader.readAsBinaryString() and reader.readAsDataUrl() (Decoded the base64 fileContent before writing to a file), but they did not seem to work.
PS :
1. Also tried reader.readAsArrayBuffer(), the resultant ArrayBuffer object shows some byteLength, but no content, and when this is passed to the server, all I see is {}.
This bit of code is intended to work on only newer versions of browsers..

Thanks N.M! So, it looks like ArrayBuffer objects cannot be used directly, and a DataView must be created in order to use them. Below is what worked -
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 N.M 's comments to the question for links to the relevant pages.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays

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>
Source file
</body>
</html>

Related

Convert _body content (string) to an arrayBuffer

I have an Ionic application which downloads a file from a Web API. The content of the file can be found in the _body property of the HTTP response.
What I'm trying to do is convert this text into an arrayBuffer so I can save the content into a file.
However, the issue that I'm having is that any file (PDF files in my instance) that have images and/or large in size either don't show up at all or show up as correputed files.
At first I thought this was an issue relating Ionic. So to make sure I tried to simulate this issue and I was able to reproduce it.
Is this snippet you can select a PDF file, then download it. You would find that the downloaded file is corrupted and exactly how my Ionic app displays them.
HTML:
<input type="file" id="file_input" class="foo" />
<div id="output_field" class="foo"></div>
JS:
$(document).ready(function(){
$('#file_input').on('change', function(e){
readFile(this.files[0], function(e) {
//manipulate with result...
$('#output_field').text(e.target.result);
try {
var file = new Blob([e.target.result], { type: 'application/pdf;base64' });
var fileURL = window.URL.createObjectURL(file);
var seconds = new Date().getTime() / 1000;
var fileName = "cert" + parseInt(seconds) + ".pdf";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = fileURL;
a.download = fileName;
a.click();
}
catch (err){
$('#output_field').text(err);
}
});
});
});
function readFile(file, callback){
var reader = new FileReader();
reader.onload = callback
//reader.readAsArrayBuffer(file);
reader.readAsText(file);
}
https://jsfiddle.net/68qeau3h/3/
Now, when using reader.readAsArrayBuffer(file); everything works as expected, however in my particular case, I used reader.readAsText(file); because this is how the data is retrieve for me, this is text form.
When adding these lines of code to try to convert the string into an arrayBuffer
...
var buf = new ArrayBuffer(e.target.result.length * 2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=e.target.result.length; i<strLen; i++) {
bufView[i] = e.target.result.charCodeAt(i);
}
var file = new Blob([buf], { type: 'application/pdf' });
...
This will not work and generate PDF files that the browser can't open.
So to recap, what I'm trying to do is somehow convert the result I get from reader.readAsText(file); to what reader.readAsArrayBuffer(file); produces. Because the files I'm working with, or the data im retrieving from my backend is this text form.

Stuck with the CSV file reading in javascript

Hi I am trying to read the csv file (just on front end not want to store it on back end ). The error I am getting is attached with the image below.
enter image description here
The code I am trying is.
function file(){
var fullPath = document.getElementById('upload').value;
if (fullPath) {
var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
var filename = fullPath.substring(startIndex);
if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
filename = filename.substring(1);
}
alert(filename);
// passFile(filename);
d3.csv(filename, function(error, data) {
if (error) throw error;
console.log(data); // [{"Hello": "world"}, …]
});
}
}
I just want to read the data from file but getting this error.
I have tried other ways too like This method I tried first but does not work for me. Can anyone help me out?
d3.csv() function is for fetching csv file from a remote location. If you want to read a local file by <input type="file"> element, you should use FileReader to read the file by yourself and parse it with d3.csvParse() function.
For example:
function file(){
var uploadFileEl = document.getElementById('upload');
if(uploadFileEl.files.length > 0){
var reader = new FileReader();
reader.onload = function(e) {
console.log(d3.csvParse(reader.result));
}
reader.readAsText(uploadFileEl.files[0]);
}
}
<input type="file" id="upload" />
<button id="upload" onclick="file()">Read CSV</button>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.1/d3.min.js"></script>

upload csv and save it to a local folder Jquery

What I would like to have happen is a when a user uploads a CSV from an HTML page that file should save to a local directory that I have provided.
One of two things should happen, if the file already exists it should overwrite, otherwise it should create a new file.
Here is the code that I have:
<!DOCTYPE html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/0.71/jquery.csv-0.71.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// The event listener for the file upload
document.getElementById('txtFileUpload').addEventListener('change', upload, false);
// Method that checks that the browser supports the HTML5 File API
function browserSupportFileUpload() {
var isCompatible = false;
if (window.File && window.FileReader && window.FileList && window.Blob) {
isCompatible = true;
}
return isCompatible;
}
// Method that reads and processes the selected file
function upload(evt) {
if (!browserSupportFileUpload()) {
alert('The File APIs are not fully supported in this browser!');
} else {
var data = null;
var file = evt.target.files[0];
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event) {
var csvData = event.target.result;
data = $.csv.toArrays(csvData);
if (data && data.length > 0) {
alert('Imported -' + data.length + '- rows successfully!');
} else {
alert('No data to import!');
}
};
reader.onerror = function() {
alert('Unable to read ' + file.fileName);
};
}
}
});
</script>
</head>
<body>
<div id="dvImportSegments" class="fileupload ">
<fieldset>
<legend>Upload your CSV File</legend>
<input type="file" name="File Upload" id="txtFileUpload" accept=".csv" />
</fieldset>
</div>
<script>
document.getElementById("data").innerHTML;
</script>
</body>
</html>
You need a server (PHP or NodeJS) that exposes this html file ( usually placed in a public folder ) and then serve this html file, you can then do the validation and the storage through the server. You could later on add a database hook, but that depends on your needs and probably the amount of data you'll be uploading.

Pass file path to javascript input android

I understand that providing a physical file path to javascript is not possible due to security reasons. However, when I look at Mozilla's pdf.js and mupdf android pdf viewer I see this is very much possible. There is a mechanism by which I can pass a file path to javascript. I explored into PDF.js but it seemed little difficult to make use of when I needed a simple solution.
I want to pass android internal storage file location onto the following code instead of using input id="files" type="file" which requires me to browse and select file. In my case I want to just pass file location from sdcard.
The following code actually loads ms word (docx) file as html which I then will show in webview in my project. In the case of pdf.js we were using it to display pdf in the similar way.
<script>
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = e.target.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
files[0],
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
</script>
<input id="files" type="file" name="files[]" multiple="false" />
<div id="loaded-layout" style="width:100%;height:800px;">
</div>
You can check code of PDF.JS based pdfviewer in android here.
What I found on the PDF.js code which was used to input file :
In pdffile.js included in index.html file, url variable was mentioned pointing to real location of the file i.e. in assets folder which then was used in pdf.js but at that point the usage seems confusing. Is there any way by which I can use real path of file or pass real path somehow in android for my purpose of viewing docx?
UPDATE :
I find that PDF.js by Mozilla actually treats file location as a url and so the file in the url is converted to javascript file object or blob. Hence I create a blob of the url from server using Ajax :
var myObject;
var xhr = new XMLHttpRequest();
xhr.open("GET","10143.docx",true); // adding true will make it work asynchronously
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200){
//do some stuff
myObject = this.response;
}
};
xhr.send();
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = myObject.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
blobToFile(myObject, "10143.docx"),
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
function blobToFile(theBlob, fileName){
//A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
However now that I do that I get Parsing error from DocxJS like : {isError: true, msg: "Parse Error."}

HTML5 FileReader, read from local file

I want to read a local binary file. So, I do this
var file = new File([""], url);
var reader = new FileReader();
reader.onload = function () {
parse(reader.result);
}
reader.readAsArrayBuffer(file);
where url is a filepath like url="c:\temp\myfile.bin"
I don't have any errors, but something is wrong, because all data from my app disappear. What could be wrong ? Any ideas ?
Thanks!
I guess you have to use input type="file" for security reasons.
Here's a working example. For convenience it shows the opened file in the same browser window.
<html>
<body>
<script>
function readFile() {
var reader = new FileReader();
file = document.getElementById("uploadText").files[0];
reader.onload = function (ev) {
document.getElementById("obj").data = ev.target.result;
// parse(ev.target.result);
};
reader.readAsDataURL(file);
// reader.readAsArrayBuffer(file);
};
</script>
<div>
<input id="uploadText" type="file" onchange="readFile();" />
</div>
<object id="obj" data="" />
</body>
</html>

Categories

Resources