I'm trying to allow users to drag and drop a folder containing JavaScript files into an html5 page. This is what I currently have:
$scope.files = [];
//Establish dropzone
var dropbox;
dropbox = document.getElementById("fileDragAndDrop");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
//Events
function dragenter(e) {
e.stopPropagation();
e.preventDefault();
};
function dragover(e) {
e.stopPropagation();
e.preventDefault();
};
function drop(e) {
e.stopPropagation();
e.preventDefault();
var items = e.dataTransfer.items;
for (var i = 0, item; item = items[i]; i ++) {
var entry = item.webkitGetAsEntry();
if(entry) {
traverseFileTree(entry);
}
}
};
//resursive file walker
function traverseFileTree(item) {
if(item.isFile) {
$scope.$apply(function () {
$scope.files.push(item);
});
} else if (item.isDirectory) {
var dirReader = item.createReader();
dirReader.readEntries(function(entries) {
for (var i = 0; i < entries.length; i++) {
traverseFileTree(entries[i]);
}
});
}
};
So the dragging and dropping works, but I'm having problems reading the file content.
$scope.parse = function () {
for(var i = 0; i < $scope.files.length; i++) {
var fileReader = new FileReader();
fileReader.onload = function (e) {
console.log(fileReader.result);
};
fileReader.onerror = function(err) {
console.log(err);
};
fileReader.readAsBinaryString($scope.files[i]);
}
};
I am not getting any error messages, which makes it hard to debug. Am I doing something wrong? has anyone had any issues doing similar tasks?
To read a file, use FileReader , which enables you to read the content of a File object into memory. You can instruct FileReader to read a file as an array buffer, a data URL, or text. // Check if the file is an image.
The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read.
Thankfully, with HTML5 we can now read files from the local file system. This means we can create apps that work better offline. The HTML input element of type="file" allows users to select one or more files from the local file system.
The main idea of the solution is: the JavaScript code cannot access the file by having its local URL. But it can use the file by having its DataURL: so if the user browses a file and opens it, JavaScript should get the "DataURL" directly from HTML instead of getting "URL".
Not sure what your $scope
is but giving it a go.
As you use webkitGetAsEntry()
I assume this is for Chrome. From the looks of it your code should give you an error. If it does not, there is likely something you have omitted. You should typically get something like:
Uncaught TypeError: Failed to execute 'readAsBinaryString' on 'FileReader': The argument is not a Blob.
in your $scope.parse
function.
There is a few issues. One is that you probably would read files as text and not as binary string. Secondly readAsBinaryString()
is deprecated, use readAsArrayBuffer()
if you want to read binary data.
Further, the webkitGetAsEntry()
returns a FileEntry
, hence why you should get the error mentioned above. To read the file you could typically do:
$scope.files[i].file(success_call_back, [error_call_back]);
For example:
function my_parser(file) {
var fileReader = new FileReader();
fileReader.onload = function (e) {
console.log(fileReader.result);
};
fileReader.onerror = function(err) {
console.log(err);
};
console.log('Read', file);
// Here you could (should) switch to another read operation
// such as text or binary array
fileReader.readAsBinaryString(file);
}
$scope.files[0].file(my_parser);
This will give you a File
object as argument to my_parser()
. Then you could typically check .type
and use appropriate read function. (Though be aware of the slackness in MIME type. As in: do not rely on it, but use it as a hint.)
if (file.type.match(/application\/javascript|text\/.*/)) {
// Use text read
} else if (file.type.match(/^image\/.*/)) {
// Use binary read, read as dataURL etc.
} else ...
$scope.parse = function () {
for(var i = 0; i < $scope.files.length; i++) {
var fileReader = new FileReader();
fileReader.onload = function (e) {
console.log(fileReader.result);
};
fileReader.onerror = function(err) {
console.log(err);
};
fileReader.readAsText($scope.files[i]);
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With