Unable to read image with FileReader (see Update 2) - javascript

I am trying read a image file selected by a input[type=file] field with this javascript code:
var reader = new FileReader();
var blob;
reader.onloadend = function (e) {
blob = e.target.result;
}
reader.readAsDataURL(this.files[0]);
but when I run the code in the browser, I am getting this error:
TypeError: Argument 1 of FileReader.readAsDataURL is not an object.
Anyone can see what's wrong here?
UPDATE
this is the code where this snippet is included. SHould given more context about what's causing the error, I hope:
$('#submit').on('click', function(){
var $form = $( 'form.form' ), url = $form.attr( "action" ), str = $form.serialize();
$('input[type=file]').each(function(){
var reader = new FileReader();
var blob;
reader.onloadend = function (e) {
blob = e.target.result;
}
reader.readAsDataURL(this.files[0]);
str = str + "\u0026" + $(this).attr("name") + "=" + blob;
});
var posting = $.post( url, str );
posting.done(function(data){
if(data == "") {
$("#alerta_sucesso").css("display", "block");
} else {
$("#alerta_erro").find("#texto").text(data);
$("#alerta_erro").css("display", "block");
}
});
});
UPDATE 2
I manage to change the code and execute it without errors, but even so I can't store the image inside the variable blob to send this data to the server. The curretn code is this:
$('#submit').on('click', function(){
var $form = $( 'form.form' ), url = $form.attr( "action" ), str = $form.serialize();
var input = $form.find('input[type=file]');
$form.find('input[type=file]').each(function(){
var id = $(this).attr("id");
if(typeof id !== "undefined") {
if(this.files.length > 0) {
var reader = new FileReader();
var blob;
reader.onloadend = function (e) {
blob = e.result;
}
reader.readAsDataURL(this.files[0]);
str = str + "\u0026" + $(this).attr("name") + "=" + blob;
}
}
});
var posting = $.post( url, str );
posting.done(function(data){
if(data == "") {
$("#alerta_sucesso").css("display", "block");
} else {
$("#alerta_erro").find("#texto").text(data);
$("#alerta_erro").css("display", "block");
}
});
});
I assume the problem now it's with the line:
blob = e.result;
Anyone knows what should be the right value for this?

FileReader is asynchronous and the execution happens in a singular thread.
This means when this line is called (I can't see str being defined anywhere, if not, remember to set it to an initial string before appending it, ie. var str = "";):
str = str + "\u0026" + $(this).attr("name") + "=" + blob;
blob is not yet filled with any value yet as it need to wait for the entire function block to finish execution so the code inside the handler can be executed.
You need to build the resulting string from within the callback:
var reader = new FileReader();
reader.onloadend = function() {
str += "&" + $(this).attr("name") + "=" + this.result;
// continue from here ...
};
reader.readAsDataURL(this.files[0]);
But blob is not a blob in this code (or this.result after my changes above), it's a string holding a data-uri at this point. You may need to encode your string first if this is intended to be part of a URI argument (see for example encodeURIComponent - with images as data-uri you may also run into length limitations and will have to use POST).
If you need an actual blob you don't even need to use FileReader - simply use the file object which is also a blob (from this.files[n]).

With the limited information given, if you're trying to show the image in a div or img element, below shows two approaches.
Solution 1
$('input').change(function() {
var fr = new FileReader;
fr.onloadend = function() {
$("#target").attr('src', fr.result);
};
console.log(this.files[0]);
//fr.readAsDataURL(this.files[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="file">
<img id="target">
Solution 2
$('input').change(function() {
var fr = new FileReader;
fr.onload = function() {
var img = new Image;
img.onload = function() {
var c = document.getElementById("cvs");
var ctx = c.getContext("2d");
ctx.drawImage(img, 0, 0, 200, 180);
}
img.src = fr.result;
};
console.log(this.files[0]);
fr.readAsDataURL(this.files[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="file">
<canvas id="cvs"></canvas>
These would read your file and you can get dynamically the file name and other properties.

So, I finally manage to solve this issue with this approach:
var str = "";
$('input[type=file]').on("change", function(){
var id = $(this).attr("id");
var name = $(this).attr("name");
if(typeof id !== "undefined") {
if(this.files.length > 0) {
reader = new FileReader();
reader.onloadend = function () {
str += "&" + name + "=" + this.result;
}
reader.readAsDataURL(this.files[0]);
}
}
});
$('#submit').on('click', function(){
var $form = $( 'form.form' );
var url = $form.attr( "action" );
str += $form.serialize();
$.post(url, str, function(data){
if(data == "") {
$("#alerta_sucesso").css("display", "block");
} else {
$("#alerta_erro").find("#texto").text(data);
$("#alerta_erro").css("display", "block");
}
});
});
and now the image is being sent to server as a string which can be handled by the PropertyEditorSupport class; this is the thing I am trying make work right now.

Related

I try to upload a image and get that image into base64 format in IE9 using javascript.but i faced issue.please any one help me

This is my javascript code.
if (typeof FileReader !== "undefined") {
var filerdr = new FileReader();
filerdr.onload = function(e) {
$('#imgprvw' + fieldno).attr('src', e.target.result);
var imgFileSize = input.files[0].size/1024/1024;
if (imgFileSize <= 1) {
var base64image = e.target.result;
console.log(base64image);
}
else {
var base64image = jic.compress(document.getElementById('imgprvw' + fieldno), 90, ext);
}
var imageBase64 = base64image.replace(/^data:image\/(png|jpeg);base64,/, "");
}
}
im using javascript for IE9.i used filereader API and polyfills also. but i didnt get the solution

Length of uploaded couchDB attachment always 0 Bytes

So...I'm new to all this stuff and I'm developing an app for android with AngularJS and Ionic Framework and try to upload an audiofile I have recorded with the cordova capture Plugin like this:
// gets called from scope
$scope.captureAudio = function() {
var options = { limit: 1, duration: 10 };
$cordovaCapture.captureAudio(options).then(function(audioData) {
uploadFile(documentID, audioData);
}, function(err) {
console.log('error code: ' + err);
});
};
var uploadFile = function (document, file) {
var baseUrl = 'urltomydatabase';
var name = encodeURIComponent'test.3gpp'),
type = file[0].type,
fileReader = new FileReader(),
putRequest = new XMLHttpRequest();
$http.get(baseUrl + encodeURIComponent(document))
.success(function (data) {
putRequest.open('PUT', baseUrl + encodeURIComponent(document) + '/' + name + '?rev=' + data._rev, true);
putRequest.setRequestHeader('Content-Type', type);
fileReader.readAsArrayBuffer(file[0]);
fileReader.onload = function (readerEvent) {
putRequest.send(readerEvent);
};
putRequest.onreadystatechange = function (response) {
if (putRequest.readyState == 4) {
//success - be happy
}
};
})
.error(function () {
// failure
});
};
How the file looks in the console.log:
Playing the recorded file on the device works nice.
But everytime I upload the recording and the upload has finished, the uploaded attachment inside the document has the length '0' in the couchDB.
How the created file looks in the database after the upload:
What am I doing wrong?
EDIT: I just found out, when I upload an image, passed from this function as blob, it works well:
function upload(imageURL) {
var image = new Image();
var onload = function () {
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
canvas.toBlob(function (blob) {
uploadFile(documentID, blob);
});
};
image.onload = onload;
image.src = imageURL;
}
So maybe the solution is creating a blob from the audiofile? But everytime I try it, my blob has the size of 0 bytes even before uploading it and I don't find somewhere a great explanation of how to convert a MediaFile object to blob...
It looks like your code does not send the content of your file as multipart attachment. To see what is really send to couchdb, capture the traffic with wireshark (https://www.wireshark.org/) or such.
This thread brought me to the solution, PouchDB purifies it. Now my upload function looks like this and can handle every file format
// e.g capture Audio
$scope.captureAudio = function () {
var options = {limit: 1, duration: 10};
$cordovaCapture.captureAudio(options).then(function (audioData) {
uploadFile(documentID, audioData, 'audio');
}, function (err) {
console.log('error code: ' + err);
});
};
var uploadFile = function (id, file, mediatype) {
var fileName = makeID();
if (mediatype == 'image') var name = encodeURIComponent(fileName + '.jpg');
if (mediatype == 'audio') var name = encodeURIComponent(fileName + '.3gpp');
if (mediatype == 'video') var name = encodeURIComponent(fileName + '.3gp');
db.get(id).then(function (doc) {
var path = file.fullPath;
window.resolveLocalFileSystemURL(path, function (fileEntry) {
return fileEntry.file(function (data) {
var reader = new FileReader();
reader.onloadend = function (e) {
var blob = b64toBlobAlt(e.target.result, file.type);
if (blob) {
db.putAttachment(id, name, doc._rev, blob, file.type).then(function () {
if (mediatype == 'video' || mediatype == 'image') getMedia();
if (mediatype == 'audio') $scope.audios.push(source);
});
}
};
return reader.readAsDataURL(data);
});
});
});
};
// creating the blob from the base64 string
function b64toBlobAlt(dataURI, contentType) {
var ab, byteString, i, ia;
byteString = atob(dataURI.split(',')[1]);
ab = new ArrayBuffer(byteString.length);
ia = new Uint8Array(ab);
i = 0;
while (i < byteString.length) {
ia[i] = byteString.charCodeAt(i);
i++;
}
return new Blob([ab], {
type: contentType
});
}

Converting image dataUrl to Blob image for AJAX POST with javascript

I have the following code which will take an image, allow the user to crop (with other code not shown or necessary for this question), and then render the image in base64 from canvas.
I need to be able to convert the image to binary, as the API endpoint its being submitted to can't take base64. I have functionality to convert to a Blob, but I'm not sure how to implement it correctly:
$(function () {
var fileInput = document.getElementById("file"),
renderButton = $("#renderButton"),
submit = $(".submit"),
imgly = new ImglyKit({
container: "#container",
ratio: 1 / 1
});
// As soon as the user selects a file...
fileInput.addEventListener("change", function (event) {
var file;
var fileToBlob = event.target.files[0];
var blob = new Blob([fileToBlob], {
"type": fileToBlob.type
});
// do stuff with blob
console.log(blob);
// Find the selected file
if (event.target.files) {
file = event.target.files[0];
} else {
file = event.target.value;
}
// Use FileReader to turn the selected
// file into a data url. ImglyKit needs
// a data url or an image
var reader = new FileReader();
reader.onload = (function (file) {
return function (e) {
data = e.target.result;
// Run ImglyKit with the selected file
try {
imgly.run(data);
} catch (e) {
if (e.name == "NoSupportError") {
alert("Your browser does not support canvas.");
} else if (e.name == "InvalidError") {
alert("The given file is not an image");
}
}
};
})(file);
reader.readAsDataURL(file);
});
// As soon as the user clicks the render button...
// Listen for "Render final image" click
renderButton.click(function (event) {
var dataUrl;
imgly.renderToDataURL("image/jpeg", {
size: "1200"
}, function (err, dataUrl) {
// `dataUrl` now contains a resized rendered image
//Convert DataURL to Blob to send over Ajax
function dataURItoBlob(dataUrl) {
// convert base64 to raw binary data held in a string
var byteString = atob(dataUrl.split(',')[1]);
// separate out the mime component
var mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
//var bb = new BlobBuilder();
//bb.append(ab);
//return bb.getBlob(mimeString);
return new Blob([ab], {
type: 'image/jpeg'
});
}
var blob = dataURItoBlob(dataUrl);
//console.log("var blob: " + blob);
//var fd = new FormData(document.forms[0]);
var image = $("<img><br>").attr({
src: dataUrl
});
image.appendTo($(".result"))
$removeButton = $('<button class="btn btn-default remove">')
.text('Remove ' + imageid.value).appendTo($(".result"))
.on('click', function () {
panel.remove();
$(this).remove();
return false;
});
$submitButton = $('<div class="btn btn-default submit"></div>')
.text('Submit ' + imageid.value).appendTo($(".result"))
.on('click', function () {
var fd = new FormData;
fd.append('file', blob, 'image.png');
//console.log("var fd: " + fd);
var xhr = new XMLHttpRequest();
var saveImage = encodeURIComponent(dataUrl);
//console.log("SAVE IMAGE: " + saveImage);
//console.log(saveImage);
fd.append("myFile", blob);
xhr.open('POST', 'http://url.com/rest/v1/utils/guid/encode?' + saveImage + '&imageid=' + imageid.value, true);
xhr.send(fd);
});
});
});
});
On Submit, I get the following in the console:
http://url.com/rest/v1/utils/guid/encode?data%3Aimage%2Fjpeg%3Bbase64%2C%2F…CiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP%2FZ
The current version in jsFiddle: LINK

How to detect '\n\r' with FileReader

I'm loading a file on my webapp and I use this function I found on a website to read it:
<script>
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 - 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;
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
</script>
The reading works fine but it seems that the "\n\r" is not read and all my lines are stick together.
Is there anything to change in this code to take account of '\n\r' ?
You can solve this problem with CSS only. Demo. MDN.
#byte_content { white-space: pre}

saving image to localstorage from form and storing/loading it

my code looks like this;
<form>
<input type="text" />
<input type="file">
</form>
<div id="notes"></div>
i got the text variables to work, however, i cannot get this silly image thing to work, i've looked at loads of tutorials but i simply cannot manage to do it
i know i have to do something with
(document.getElementById("file").files)[0] != null) {
var pic = (document.getElementById("file").files)[0];
var imgUrl;
var reader = new FileReader();
reader.onload = function(e) {
var imgURL = reader.result;
saveDataToLocalStorage(imgURL);
reader.readAsDataURL(pic);
for the image and then use the JSON.parse to get the url back and show it on the page
but i cannot figure out how it works, neither can i find any examples that aren't too complicated to implement it into my own code
in this fiddle i have provided all the code that i have at the moment
http://jsfiddle.net/VXdkC/
i really hope you guys can help me out, i've been messing around with this thing the past 2 days and it's starting to frustrate me :(
Here's how I'd do it :
var notes = localStorage.getItem('notes'),
arr = [];
if (notes) {
arr = JSON.parse(notes);
$.each(arr, function(k,v) {
console.log(v)
var h1 = $('<h1 />', {text: v.title});
var p = $('<p />', {text: v.msg});
var img = $('<img />', {src: v.image});
$('#notes').append(h1, p, img);
});
}
$('#clear').click(function () {
if (confirm('This will clear all notes, are you sure?')) {
window.localStorage.setItem('notes','');
location.reload();
}
return false;
});
$('#addNote').click(function () {
var Title = $('#title').val();
var Message = $('#message').val();
var file = $('#file').prop('files')[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
var b64 = e.target.result;
var note = {
image : b64,
title : Title,
msg : Message
}
arr.push(note);
localStorage.setItem('notes', JSON.stringify( arr ));
$('#notes').prepend("<div class='entry'><h1>" + Title + "</h1></p>" + "<p>" + Message + "<img src=" + b64 + " /></p> </div>");
}
return false;
});
FIDDLE
Its pretty simple
var pic = document.getElementById("file").files[0];
var imgUrl;
var reader = new FileReader();
reader.onload = function(e) {
var imgURL = reader.result;
$('#notes').prepend("<div class='entry'><h1>" + Title + "</h1></p>" + "<p>" + Message + "<img src=" + imgURL + "></p> </div>");
var notes = $('#notes').html();
localStorage.setItem('notes', notes);
saveDataToLocalStorage(imgURL);
}
reader.readAsDataURL(pic);
http://jsfiddle.net/VXdkC/2/
Live demo here (click).
the html:
<input id="file" type="file">
the js:
var fileInput = document.getElementById('file');
fileInput.addEventListener('change', function(e) {
var reader = new FileReader(); //create reader
reader.onload = function() { //attach onload
//do something with the result
console.log(reader.result);
localStorage.img = reader.result; //saved to localStorage
createImg(localStorage.img); //retrieved from localStorage
};
var file = e.target.files[0];
reader.readAsDataURL(file); //trigger onload function
});
function createImg(dataUri) {
var img = document.createElement('img');
img.src = dataUri;
document.body.appendChild(img);
}

Categories