html 5 + webkitRequestFileSystem: save image file from user - javascript

using webkitRequestFileSystem, I want to do something very simple: get a file from user, save it to browser local filesystem, and use it later (for example as image src etc)
I read about webkitRequestFileSystem but I didn't find anything about cloning files from user (maybe I missed it?).
so I tried a naive implementation of reading, getting file, writing, and everything seems to works (calls the success callback), and I can see the file with a chrome extension (HTML5 filesystem explorer), but when I try to use the image url it shows a broken image icon.
here's the snippet to clone the file (sort-of, had to clean it up a little):
var src_file = .... <-- got it from user
filesystem.root.getFile("output.png", {create: true}, function(dest_file)
{
var reader = new FileReader();
reader.onerror = function() {alert("ERROR")};
reader.onload = function(e)
{
read_buffer = e.target;
dest_file.createWriter(function(fileWriter) {
var blob = new Blob([read_buffer.result], {type: 'application/octet-stream'}); // <-- also tried "image/png" etc..
fileWriter.onerror = function() {alert("ERROR2")};
fileWriter.onwriteend = function(writer)
{
alert("SUCCESS!");
};
fileWriter.write(blob);
}, function() {alert("ERROR3")});
};
reader.readAsBinaryString(src_file);
});
PS I work on localhost, is that an issue?
Thanks!

answering myself: should have used readAsArrayBuffer() instead of readAsBinaryString()... what a waste of time that was :/

Related

How to get full path to user's type="file" using jQuery Fileupload

Im trying to build file preview feature before file being uploaded to the server.
Im stucked with the problem of reading file from the user's computer, not a server
Im usuing jquery Fileupload which fires the file processing on the change function
return $('#new_order_file').fileupload({
change: function(e, data) {
return $.each(data.files, function(index, file) {
read_file(file);
console.log(file)
});
},
});
Log gives File - name, size, type, proto and LastmodifiedDate
Than, this part is tricky for me, I know that I have to use FileReader() but Im not sure how to
function read_file(f){
var reader = new FileReader();
reader.onload = function(e) {
$('#CO-show-model').css('display', 'block');
loaded(f.name, e.target.result);
};
reader.readAsArrayBuffer(f);
}
Next, loaded function is for displaying the file model using three.js
function loaded(file) {
var uploaded_file = file // gives 404
// var uploaded_file = './stl/test-file.stl' // ASCII test
}
The fucntion itself is good, I tested it with an hardcoded path to some test file. But the problem is that it was on a server. Now, script gives an 404 for http://example.com/filename.stl which is true, because I pass file.name there. If I just pass file, it gives 404 for http://example.com/[object%20File]
Edit 1:
I tried suggest ReadAsDataUrl, but seems to be that it's not supported by three.js. Also, the FileReader() seems to be ok
Your file is an object so you have to get the right attribute from it.
Take a look here Filereader Mozilla documentation
It's a security feature. Browsers will not give you the actual local url to the file you are uploading.
See How to get full path of selected file on change of <input type=‘file’> using javascript, jquery-ajax?
Edit: Maybe what you are looking for is this question instead? What is the preferred method for loading STL files in Three.js

Cordova - Reading Large Image corrupts image

I am using the image-picker (cordova-imagePicker) plugin in order to get images from gallery and upload them to a server.
I am using Cordova 6.1.1 with Android platform 5.1.1 and the following plugins:
cordova-plugin-camera 2.2.0 "Camera"
cordova-plugin-compat 1.0.0 "Compat"
cordova-plugin-device 1.0.1 "Device"
cordova-plugin-file 4.2.0 "File"
cordova-plugin-imagepicker 1.1.0 "ImagePicker"
cordova-plugin-inappbrowser 1.4.0 "InAppBrowser"
cordova-plugin-media 2.3.0 "Media"
As callback to the plugin, I am converting the path I get to a File using the following code. Note that I use resolveFile because this code is running also in desktop in which case, the entry is already a File object.
var resolveFile = function(entry) {
if (typeof(entry) === "string") {
var deferred = $q.defer();
// first convert to local file system URL
window.resolveLocalFileSystemURL(entry, function(fileEntry) {
// now read/convert the file to file object.
fileEntry.file(function(file) {
console.log("File converted to file entry");
deferred.resolve(file);
}, function(err) {
console.log("Failed to convert to file entry", err);
deferred.reject(err);
});
}, function(err) {
console.log("Failed to resolve to file URL", err);
deferred.reject(err);
});
return deferred.promise;
} else {
return $q.when(entry);
}
};
This, in turn is used to read the image and pass it to a function that uploads it to the server ($files is what I am getting from plugin or from input in case of desktop/browser):
var upload = function () {
if (!$files[currentFile]) {
onAllFinished();
return;
}
file = $files[currentFile];
beforeLoad(file);
fileReader = new FileReader();
fileReader.onload = onload;
fileReader.onprogress = progress;
resolveFile(file).then(function(actualFile) {
fileReader.readAsDataURL(actualFile);
});
currentFile++;
};
In the above, onload cuts the image data (following 'base64,' in string) and sends it to the the upload code which expects a base64 string and uploads the data to the server using simple AJAX call:
var uploadPhoto = function(url, photo, callback, error)
$http.post(url, {
photo: photo,
})
.success(callback)
.error(function (data, status, headers, config) {
if (error)
error(data, status, headers, config);
});
The last function works also with the camera plugin camera plugin using DATA_URI target (I know, it's not recommended) which also return a base64 string (so I can reuse the code).
It seems to me there's something wrong going on with the file reader output (I am guessing). What (I think) hints to that is that small images (10s kb) are loaded fine as well as already prepared base64 string from camera plugin but larger images (few MBs) that goes through the filereader (on Android, on desktop it is fine) are uploaded corrupted (see below).
Has anyone run into such issues? Can anyone suggest a fix (other than changing the code to use FileTransfer plugin)?
The original image:
The uploaded (corrupted) image. Note, some of it is read/uploaded fine:
I found your question while searching for a solution for a similar problem. DataURL's of large images from camera would show up when used as the source of an image but the same image got corrupted when I use fileReader.readAsDataURL.
I've been able to bypass the problem by using fileReader.readAsBinaryData instead of fileReader.readAsDataURL and then turning the binarystring into a dataURL.
window.resolveLocalFileSystemURL(imageUri, function done(fileEntry) {
fileEntry.file(function (fileObj) {
var image = new Image();
var reader = new FileReader();
reader.onloadend = function (e) {
image.src = "data:image/jpeg;base64," + window.btoa(e.target.result)
}
reader.readAsBinaryString(fileObj);
}
}
Hopefully this helps you to find a workaround of your own.

how do i get any images in binary code using js?

I want to make a multiple images upload system with prograss bar. I want to do with simaple code(using jquery or js). I want when user has upload his images on browser and i want to show on browser that images and with upload button he starts uploading image via ajax in his folder.
So questions
1.) Is it possible to show uploaded image (without any complicated code) ?
2.) Do i get a variable or array where uploaded images are stored as base64 code (data:/img:dfd5d/d54fs..... something like this) or encoded?
3.) How do i add progressBar ?
I didn't write any code yet because i dont know how to start. I am new in computer science.
But i find this code on this site
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
This is easy code and i understand but one thing is not clear what does mean this line var reader = new FileReader(); why use new and what is it ?
Ty in advance and please dont explain complicate and i am not very good in english. So please try to explain in poor words if possible..
Assuming that you have this field
<input type="file" onchange="showImage(this)"/>
you can create a script to take the binary data and show it
function showImage(input){
var reader = new FileReader();
// validating...
var fileType = input.files[0].type;
var filesize = input.files[0].size;
// filetype (this will validate mimetype, only png, jpeg, jpg allowed)
var fileTypes = ["image/png", "image/jpeg", "image/gif"];
if (fileTypes.indexOf(fileType) < 0){
// return error, invalid mimetype
return false;
}
// file cannot be more than 500kb
if (filesize > 5000000) {
// return error, image too big
return false;
}
reader.onload = function (e) {
// e will contain the image info
jQuery('#myimagetopreview').attr('src', e.target.result)
}
reader.readAsDataURL(input.files[0]);
}
This should work, if you have problem tell me
edit: FileReader is not supported by all the browsers, check the documentation for more https://developer.mozilla.org/en/docs/Web/API/FileReader
The FileReader in JS has Status "Working Draft" and isn't part of the official JS API. I think you have to wait until the Browsers support this ne API or you have to activate experimental JS API in the Browser.

How do i remove files from a zip file uploaded through kendoUpload? Using jszip

After the user uploads a zipped file, i want to remove the images folder from it before sending it over the network. I am using kendo for uploading, and the existing functionality works fine. I just want to add on the removing images part. This is what i have so far:
function onSelect(e) {
var file = e.files[0];
if (endsWith(file.name, '.eds')) {
var contents = e.target.result;
var jszip = new JSZip(contents);
jszip.remove("apldbio/sds/images_barcode");
fileToSend = jszip.generate({type: "base64", compression: "DEFLATE"});
}
e.files[0] = fileToSend;
openProgressDialog(e.files.length); //this is existing code, works fine
}
target.result doesn't seem to exist in the event e. And nothing works properly from that point on. e should probably be used inside a FileReader object's onload(), (as seen here and here) but i have no idea how to use a FileReader for my purpose, with kendo Upload.
EDIT:I did some more reading and now i am using FileReader like this:
var reader = new FileReader();
reader.onload = function (e) {
// do the jszip stuff here with e.target.result
};
reader.onerror = function (e) {
console.error(e);
};
reader.readAsArrayBuffer(file);
Note : file = e.files[0] as in the 1st code block.
With this though, i get the error:
Failed to execute 'readAsArrayBuffer' on 'FileReader': parameter 1 is not of type 'Blob'.

HTML5 File API crashes Chrome when using readAsDataURL to load a selected image

Here's my sample code:
var input = document.createElement('input');
input.type = 'file';
document.body.appendChild(input);
input.addEventListener('change', function(){
var file = input.files[0];
var reader = new FileReader();
reader.onload = function(e){
var image = new Image();
image.src = e.target.result;
};
reader.readAsDataURL(file);
});
Load the page, select a large image (I'm using a 2.9MB 4288x3216 image). Refresh the page and select the same image. Result? The tab crashes! (Aw, Snap!)
My guess is that this is a bug with Chrome's implementation of the File API, but I'd love it if someone could confirm that and maybe even offer a workaround. I really want to be able to show a thumbnail of a photo without having to go to the server to generate one (even if it's just for Chrome and FF).
Also, with my sample code above, as soon as you select the photo, the tab starts using about 32MB more of memory. That, I guess, is expected, but what concerns me is that the memory never seems to get freed by the garbage collector. So if I keep selecting more photos, I keep consuming more memory. I don't know if this is related to the crashing issue or not, but it's definitely a concern.
Thanks for any help!
The memory issue could be a result of this bug: http://crbug.com/36142. Essentially, Chrome is caches data: URLs and currently does not release the memory when the img.src is changed. The other issue is that data: URLs yield a 33% overhead to the data you're encoding. That means you're actually setting a ~3.85MB resource on the image, not 2.9MB.
Since you're not manipulating the content (the actual bytes), there's no need to read the file content. One option is to create a blob: url. There's also an explicit revoke method, so you won't run into the same memory caching issues. Something like:
input.addEventListener('change', function(e) {
var file = input.files[0];
window.URL = window.webkitURL || window.URL; // Vendor prefixed in Chrome.
var img = document.createElement('img');
img.onload = function(e) {
window.URL.revokeObjectURL(img.src); // Clean up after yourself.
};
img.src = window.URL.createObjectURL(file);
document.body.appendChild(img);
});

Categories

Resources