javascript to read file selects a file but doesn't read it - javascript

My script selects a file... but doesn't read it. I've been banging my head on it but can't make it work. It's part of my studies, I'm a greenhorn and I'm lost.
function readBlob() {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
var file = files[0];
var start = 0;
var stop = file.size;
var reader = new FileReader();
if (file.webkitSlice) {
var blob = file.webkitSlice(start, stop);
//Creates new blob if using google chrome
} else if (file.mozSlice) {
var blob = file.mozSlice(start, stop);
//Creates new blob if using mozilla firefox
}
//read the contents of the file in as text into the blob
reader.readAsText(blob);
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) {
document.getElementById('byte_content').textContent =
evt.target.result;
}
};
}
}

Seems like a simple syntax error to me, but maybe just an error inserting it into stack overflow. The entire thing, the slicing of the file, the insertion into the document, everything, is inside of the if (!files.length) statement. Therefore, the script only executes when there is no file (catching on to the problem yet :) but it is actually meant to do the opposite. All of the important stuff is supposed to be outside of the if statement.

Related

Sending videos from the client to the server

I recently read about the File API which allows the client to use files from the file system in the website.
I did all the stuff of adding the file input tag and reading the file and everything.
I read the file as ArrayBuffer using a FileReader and used a Uint8Array view on it, then I send the view to the server.
I tried it with txt, pdf and images and it worked fine. But when to use it with video files the computer lagged that and I didn't even wait and closed the browser!
Here's the code
Why did the lag happen with video files and is there a way to avoid it?!
I gone through the code, you are appending the read data pushed into the array which may be the reason why it lags.
You need to upload the video in chunks. To make a chunk of file you choose, you can take a look here
HTML5 file reader api
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons')
.addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
You need to modify according to your requirements. Here when you get the chunk, make a request to upload it or play it.
Also you can play with you video file here
Upload your Video file here to test
Hope this solves your problem. To get this working you need to handle the chunks properly on the backend as well.

Why am I missing elements in my array from array.from()

I am currently building a large database from an imported XML document, about 13k items or so. When I do
window.onload = function() {
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function(e) {
let text = reader.result;
let parser = new DOMParser();
xmlDoc = parser.parseFromString(text,"application/xml");
getReportList(xmlDoc);
}
reader.readAsText(file);
} else {
fileDisplayArea.innerText = "File not supported!";
}
});
}
function isGroupTag(arr) {
return arr.nodeName === "Group";
}
function getReportList(xml) {
// Creates an array containing all reports
let reportList = Array.from(xmlDoc.children[0].children).filter(isGroupTag);
allReports = reportList.map((currElement, index) => {
return getReport(xml, index);
});
}
I only get back about 2100? I checked my program using a much smaller XML document and every thing was loaded fine. Any ideas as to why I would be getting such a small return back?
My first thought was that the XML document wasn't loaded completely yet so when I did Array.from() it was building the array with what it had...not sure though. Any help would be great.
EDIT:
I just finished testing loading in a few more XML documents. Instead of one massive file I loaded in the yearly ones and everything shows up. Still not sure why I can't just do the massive one.

What's DataTransferItemList and what is DataTransferItemList.add doing?

So I'm trying to understand paste and copy API in Google Chrome. I don't understand either.
As of copy, you'll probably want to use javascript to add something in clipboard. I'm working with images (strings work well actually1):
//Get DataTransferItemList
var files = items.items;
if(files) {
console.log(files);
//Create blob from canvas
var blob = Blob.fromDataURL(_this.editor.selection.getSelectedImage().toDataURL("image/png"));
var file;
try {
//Try to create file from blob, which may fail
file = new File([blob], "image.png", {type:"image/png"});
}
catch(e) {
return false;
}
if(file) {
//I think this should clear previous data from clipboard
files.clear();
//Add a file as image/png
files.add(file, "image/png");
}
//console.log(files.add(file));
}
The problem is, that I don't really know how does that add method work. I found this "documentation" for DataTransferItemList which says:
add(any data, optional DOMString type)
What's any data? (how can anybody even write this in documentation?) While something is added to clipboard, I don't know what it is. I can't paste it anywhere - except Chrome. If I inspect paste event with my copied file, this is in DataTransferItemList:
It can be converted to File, but if I try to turn it back to <img>:
ImageEditorKeyboard.prototype.processFile = function(file) {
//File reader converts files to something else
var reader = new FileReader();
//Refference to this class
var _this = this;
//happens when the file is loaded
reader.onload = function(event) {
var img = new Image;
img.onload = function() {
_this.processImage(this);
};
img.src = event.target.result;
}; // data url!
//Read file
reader.readAsDataURL(file);
}
I get the error2:
If I log the value of event.target.result it turns out that the data was empty:
console.error("String '", event.target.result, "' ain't a valid URL!");
Q: What is the exact specification of DataTransferItemList, it's methods and properties, especially the .add method?
1: To add string to clipboard (during copy event of course!), call this: event.clipboardData.setData(data, "text/plain");. The second argument doesn't seem to have any functionality - using image/png will not do anything.
2: Funny thing is that this error can't be caught.

HTML 5 File API 0x80004003

Hi i am using the JS HTML5 File API to handle file uploads to my server.
I am getting the following error in Aurora(Fire Fox Bleeding edge builds)
NS_ERROR_INVALID_POINTER: Component returned failure code: 0x80004003 (NS_ERROR_INVALID_POINTER) [nsIDOMFileReader.readAsBinaryString]
function readBlob(opt_startByte, opt_stopByte,file,partNo) {
var start = parseInt(opt_startByte);
var stop = parseInt(opt_stopByte);
var reader = new FileReader();
var totalParts = parseInt(file.size/MAX_READ);
if((file.size % MAX_READ) !== 0){
totalParts++;
}
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) {
//var contents = reader.result;
postFilePart(partNo,contents,totalParts,escape(file.name))// DONE == 2
}
};
if (file.webkitSlice) {
var blob = file.webkitSlice(start, stop);
} else if (file.mozSlice) {
var blob = file.mozSlice(start, stop);
}
reader.readAsBinaryString(blob);
}
the error is occurring at this line
reader.readAsBinaryString(blob);
i have tried mozSlice and Slice
if (file.mozSlice) {
var blob = file.mozSlice(start, stop);
}
and it gave me the same results. it might not be the best idea to use HTML 5 API yet as this may cause issues with other browsers as well.
does anyone have a work around to get the same functionality or how i can resolve this particular error
Solved the issue it it was rerunning the reader code with incorrect parameters due to a mistake on the calling method
https://bugzilla.mozilla.org/show_bug.cgi?id=725289
rather use slice vs mozSlice

HTML5 File API: get File object within FileReader callback

With the new File API in Javascript you can read files in Javascript to create dataURLs to show clientside pictures clientside. I'm wondering if you can reach the File object within the FileReader's onload callback.
I will illustrate this with an example:
var div = document.createElement('div');
div.ondrop = function(e) {
e.preventDefault();
e.stopPropagation();
var files = e.dataTransfer.files;
for ( var i=0; i<files.length; i++ ) {
var file = files[i]; // this is the file I want!!
var filereader = new FileReader();
filereader.onload = function(e) {
this; // the FileReader object
e.target; // the same FileReader object
this.result; // the dataURL, something like data:image/jpeg;base64,.....
var img = document.createElement('img');
img.src = this.result;
img.title = file.fileName; // This won't be working
document.appendChild(img);
}
}
return false;
}
What I could do - what I do right now - is wrap the contents of the for loop in a function and execute it to create a new scope and keep a file in that scope like so:
for ( var i=0; i<files.length; i++ ) {
var _file = files[i]; // this is the file I want!!
(function(file) {
// do FileReader stuff here
})(_file);
}
I was just wondering... Maybe I'm missing something. Is there a way to get the File object from within the onload function of the FileReader? Both this and e.target are the FileReader object and not the File. Is there something in this or e that is the File?? I can't find it :(
Thanks a bunch.
PS. A fiddle: http://jsfiddle.net/rudiedirkx/ZWMRd/1/
I already found a way. Maybe not better than the scope wrapper, but I think it's neater:
for ( var i=0; i<files.length; i++ ) {
var file = files[i]; // this is the file I want!!
var filereader = new FileReader();
filereader.file = file;
filereader.onload = function(e) {
var file = this.file; // there it is!
// do stuff
}
}
There is now a much easier (apparently faster) way (sync!) to get a file's data URL:
img.src = URL.createObjectURL(file);
Demo on http://jsfiddle.net/rudiedirkx/ZWMRd/8/show/ of both methods, and the original problem illustrated (drag multiple images and check the title tooltips).
I don't think this.file is still supported. When I try to run the answer code, this.file is undefined whereas if I run the code from the question I get the expected results. I think you have to use the closure (at least this is how they do it on html5rocks (Example)).

Categories

Resources