javascript - getting object HTMLImageElement instead of base64 string - javascript

This is a continuation to my previous question but the issue is new and the solution from that question didn't help. This is a new question.
Here's the link to my previous question where I asked how to convert canvas to an image: javascript- unable to convert canvas to image data
And I'm hoping to get the base64 encoded string of the image which I can send to a PHP service via AJAX call and PHP service is gonna convert it to image and move it to a specified directory.
Function that converts canvas to image
function convertCanvasToImage(canvas)
{
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
This is the form I created:
var url = 'url to php service';
var file = dataURL; //this is the image url that i'm sending
console.log(file);
var formdata = new FormData();
formdata.append("base64image", file);
formdata.append('csrf_test_name',csrf_token);
var ajax = new XMLHttpRequest();
ajax.addEventListener("load", function(event) {
uploadcomplete(event);
}, false);
ajax.open("POST", url);
ajax.send(formdata);
I tried console.log() the image that canvas returned and this is what I obtained:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4nGzbZ3Mba5au6fqvJ2JiTs/pPtVV20j0sOm9T3iARqI3IOi9SIoGHqATJe29q/v8jXs+QMWeHT0fnkgGyUgCiRfIi2ut9y9OqYGZ3yKqHWHlttFiCz1nE8Q+XuDiuSb5XEBccYgrDv6si5ZTMOZMzHkLMS6gFspI8TxiOEfkfCS0P1AM1lmcPaJYPcbyNvDDHUqVU5zdTaS1j4hFm3Erg5bxCK0KxXiWUm6OcLaAW46xCzZBNcAOF3FzK8TBIoG7QC7v4AUalqdRquVQZxeQa/PYc2vYc2uUnWUCuYovR+TMEoEVY8oOnhES2jlKVo2au0DZXiVSF/DciDDMUyjOEuerGGqJYm6VaG6DhBahOyW8eB4rrBGVl5BmZ5FmZ1HyLlrJZ37ep1jUyXseOdel7FWpBrMUgwXy3ixGJGLlZLRIxipoh...Hd7sRkseD2ebFF/Bj9btUYEnDzGHRy57XgcDiw2WyYDPdYzFp0dgvXBh0XeiPmYBit2YzBbufR4uDR4kBrd3BtNHHvs6ty3HJru+beoUXn0vPgNaD1Gbl1udFYbWhMFlU2E7du+zTmRWt75MGqw+axYvNYebRpMbmNaF0OzEE/+nQAXcrHpeBAk7BzJTm4zXg4Kdq4afq4nGS4fslyO85x1IizEbWwJzo5Lzu4bfk560Y5agY57SfYawS57sS4akfRFJxc5B1cl7XcVh85Gfo47HvYaFvY6ds5Hvg5GQY4bUY5rofQtAUumgk0XVXXozSXQxX+rnsSt20nmrqFG+URbdHMVSOGphbmrCNw1hG46Dg4aaoxP0c1B0dVD7sFO0cFG0cFG+fKNSeyhjPhBI10zmnqnPP0xRQAD1Pqs7CSV7VV3mCztM5Rbpnz8joXHSPXfQuXPQ9XAy9noxgXE4HT/8pz8X/L/D+QyAVhXuteXgAAAABJRU5ErkJggg==">
It has image tag. Maybe it's because of that; when I pass it to PHP service, it's not able to convert it. This is what it returned me when I debugged
object HTMLImageElement
I tried to convert the above mentioned image tag to base64 using a function like given below but it failed.
function encodeImageFileAsURL(cb) {
return function(){
var file = this.files[0];
var reader = new FileReader();
reader.onloadend = function () {
cb(reader.result);
}
reader.readAsDataURL(file);
}
}
Can anyone help me understand what i am missing here? Thanks a lot!
Reference:
https://davidwalsh.name/browser-camera
https://davidwalsh.name/convert-canvas-image

You already have a data URI at the src of the <img> element at variable image. Pass the value of the src of the <img> element to php, not the html <img> element.
var file = image.src; //this is the image url that i'm sending

Related

how to upload separately selected files in form POST request? [duplicate]

This question already has answers here:
Uploading multiple files using formData()
(18 answers)
Closed 5 years ago.
What I want
People click add image button, they select an image, image is added to gallery.
They can delete images by clicking cross sign and re click add image button to add more images.
This all works, I've a reference to all File elements.
However, I can't figure out how to send the files in post request of form.
Problem the problem is that You can't create FileList out array of file, or set array of files as input.files = arrOfFiles.
Input element itself doesn't let you add more files, or remove files... it simply replaces old file with new file(s).
which is not what i want therefore i'm keep reference to file objects in js, and letting user remove images or add more.
I know i can send individual file as XHR, but I want to send them through form that already exists.
I wanted to know a way to send files through form not js, but apparently that's not possible
That's exactly what the FormData API is for: create from scratch a form's data that you will be able to upload to your server as if it were created from a <form> object, except that you can control what goes there or not.
So to append a File or a Blob in a FormData, the code is
var fd = new FormData();
fd.append(field_name, blob, file_name);
To append multiple files, you can call again fd.append, but note that backend often need to have the field_name formatted in such a way they can know multiple values are expected here.
Usually this is done by adding [] after your fieldname.
var fd = new FormData();
fd.append('files[]', blob_1, file_name_1);
fd.append('files[]', blob_2, file_name_2);
And then you can send it through an AJAX request to your server, which won't make the difference between this request and a real one made froma single <input multiple name="files[]">.
Note that in case of File, file_name is optional and will default to the File's name if not set. However, it is needed for Blobs if you don't want a random name to be set.
var file_1 = new File(['foo'], 'file1.txt',{type:'text/plain'});
var file_2 = new File(['bar'], 'file2.txt', {type:'text/plain'});
var fd = new FormData();
fd.append('files[]', file_1);
fd.append('files[]', file_2);
console.log(...fd.entries());
// and to send it to your server
var xhr = new XMLHttpRequest();
xhr.open('POST', 'your_server_url');
xhr.send(fd);
If you are just going to upload images. Consider using base64 encoding. That is what I did. Assign base64 encoded URL to stringify JSON, or whatever you wish that is easier for you.
When the data is POST-ed, do the conversion there, to get back your files for saving them. Decoding base64 will be dependent on your backend language though of which you did not mention in your question.
In JavaScript, you can use this function to load up the image in preview state like you mentioned.
function previewImage (inputId, eleId) {
if (window.FileReader) {
var oPreviewImg = null, oFReader = new window.FileReader(),
rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;
oFReader.onload = function (oFREvent) {
if (!oPreviewImg) {
var newPreview = document.getElementById(eleId);
oPreviewImg = new Image();
oPreviewImg.style.width = (newPreview.offsetWidth).toString() + "px";
oPreviewImg.style.height = (newPreview.offsetHeight).toString() + "px";
if(newPreview.children.length > 0)
newPreview.replaceChild(oPreviewImg, newPreview.children[0]);
else
newPreview.appendChild(oPreviewImg);
}
oPreviewImg.src = oFREvent.target.result;
// Add Bootstrap's img-thumbnail class to the image frame
oPreviewImg.classList.add("img-thumbnail");
};
return function () {
var aFiles = document.getElementById(inputId).files;
if (aFiles.length === 0) { return; }
if (!rFilter.test(aFiles[0].type)) { alert("You must select a valid image file!"); return; }
oFReader.readAsDataURL(aFiles[0]);
}
}
if (navigator.appName === "Microsoft Internet Explorer") {
return function () {
document.getElementById(eleId).filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById(inputId).value;
}
}
};
Then you can extract the base64 URL from the src attribute of the img element.
You may come out with your own preferred method of "cancelling" your upload by maybe destroying the img element.

JavaScript FileReader Massive Result

I've got a FileReader that lets the user upload a file (image) to my site.
Here's the code that does the reading:
$("input[type='file']").change(function(e) {
var buttonClicked = $(this);
for (var i = 0; i < e.originalEvent.srcElement.files.length; i++) {
var file = e.originalEvent.srcElement.files[i];
var img = document.createElement("img");
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
console.log(reader.result);
}
reader.readAsDataURL(file);
}
});
All is good and well, until I tried to print out my result. I used this file for example:
When I console.log() the result, it spits out over 95000 characters.
This image in particular is around the same size as the images I will be accepting into my site.
I was hoping to store these images in a database as well, and so I'm wondering how this is going to be possible with image sources that are so extremely long. Is there a way to shorten this or get the image path a different way?
I'm moreso curious as to why they're so long, but if someone has a tip to store these (100s per user, 500+ users) that'd be nice as well!
Thanks-
Store the Files as ... Files.
There are very little use cases where you need the toDataURL() method of the FileReader, so every time you use it, you should ask yourself why you need it.
In your case :
To display the image in the page. Well don't use a FileReader for this, instead create a direct pointer to the file in the form of an url, available only to this session. This can be achieved with the URL.createObjectURL(File_orBlob) method.
To store this image on your server. Don't store a ~37% bigger base64 version, send and store directly the file as a file (multipart). This can be achieved easily with the FormData API.
inp.onchange = function(){
var file = this.files[0];
if(file.type.indexOf('image/') !== 0){
console.warn('not an image');
}
var img = new Image();
img.src = URL.createObjectURL(file);
// this is not needed in this case but still a good habit
img.onload = function(){
URL.revokeObjectURL(this.src);
};
document.body.appendChild(img);
}
// not active but to give you da codez
function sendToServer(){
var file = inp.files[0];
var form = new FormData();
// here 'image' is the parameter name where you'll retrieve the file from in the request
form.append('image', file);
form.append('otherInfo', 'some other infos');
var xhr = new XMLHttpRequest();
xhr.open('post', 'yourServer/uploadPage')
xhr.onload = function(){
console.log('saved');
};
xhr.send(form);
}
<input type="file" id="inp">
And if you need PHP code to retrieve the File form this request :
if ( isset( $_FILES["image"] ) ){
$dir = 'some/dir/';
$blob = file_get_contents($_FILES["image"]['tmp_name']);
file_put_contents($dir.$_FILES["image"]["name"], $blob);
}
You're going to want to upload the files to a server of some sort (a backend that is serving up your javascript), and then from there you'll want to
Validate the file
Store the file on a physical server (or the cloud) somewhere
Add an entry in a database that relates the file path or ID of that upload to the user who just uploaded it (so you can retrieve it later if needed)
So basically, you don't store the image in your database, you store it on a file share/cloud host somewhere, and instead you only store what is needed to download/retrieve the image later.

Converting File object to Image object in JavaScript

So I have a website (using AngularJS) that lets users upload files via tag
<input type="file" ng-model="image" id="trigger" onchange="angular.element(this).scope().setFile(this)" accept="image/*">
When I handle the upload in the controller the image gets stored as a File object. This is my method that saves the file and also sets variables to preview the image
$scope.setFile = function (element) {
$scope.image = element.files[0]; // This is my image as a File
var reader = new FileReader();
//This is for previewing the image
reader.onload = function (event) {
$scope.image_source = event.target.result;
$scope.$apply();
}
reader.readAsDataURL(element.files[0]);
}
Now I am trying to compress the image using J-I-C library found here: https://github.com/brunobar79/J-I-C/blob/master/src/JIC.js
But this library accepts an image object as its parameter and returns it as a compressed image object. I can't seem to find a way to convert my $scope.image File object into an Image object. How would I go about doing this?
I would also need to convert the compressed image object back into a File so I can upload it to my Azure storage.
You just need to create an Image instance, and set it's src to your data url. Then pass it to JIC:
var img = new Image();
img.src = $scope.image_source;
jic.compress(img,...)
It then just uses a canvas element to manipulate the image, generate a new data url, and creates a new Image instance, setting its src to the data url. So when you get the compressed image back just take the src and use atob to decode the base64 encoded data back into binary and create a Blob. You can use Blob in most places that you would use File, for instance like uploading through ajax.
var newImg = jic.compress(oldImg,...);
//replace 'image/png' with the proper image mime type
var base64data = newImg.src.replace("data:image/png;base64,","");
var bs = atob(base64data);
var buffer = new ArrayBuffer(bs.length);
var ba = new Uint8Array(buffer);
for (var i = 0; i < bs.length; i++) {
ba[i] = bs.charCodeAt(i);
}
var blob = new Blob([ba],{type:"image/png"});
//now use blob like you would any other File object

How to turn a string of data into an image in Javascript?

I have a URL of an image that when I set the src of an img to, the img changes to the image on the URL.
I want to download this image as a string so I can store it in local storage.
So I get the image data using XMLHttpRequest and this returns data that looks like this:
�T��ǁ�Y�k����De,�GV��<A:V��TɕH'�:A�
a��.e��E�ʓu�|���ʘ�*GN�'��қ��u�� ��c��]�
�.N���RH!�O�m�Aa���Զ�0U #Pɬ��:�շ���
p�;2��Z���H����¯��P�un>�u�uj��+�쨯
��Z��֦DW>U����.U:V�{�&(My��kύO�S�������e��ԃ����w�
1��j2�Ŭo�#����>ɛP���:E�o}\O���r ��Ύ�
ob�P|b��/e�\#����k>��?mr<�ƭ�0~����f����\�i�^���ޟj��ٙI&=��B���N��(�N��C�kO�o3e�az�G
�|�����AO�A�6�2
�H�^�5��$�Ѭ
\��|x�+�0 ͤ,n�|������B����
w4ɞG�Q!�"�yb#�[A��\m)��߂�dA�h�.��6����q�αA0�bO��20*�LVX�<`Rv�W�6�f'hF���V���n`̌v�7�Ν��OI|���Ԙ�uoqk���n����g��a��ӗ>���Ԏt��
I'm not sure what format this data is in. It could be Base64 based on some Google searching but not 100% sure. This is just what I get when I console.log it. The image data string has a length of 109095. The console freezes when I log this string, can't figure out why.
I then try to set the src of the img in javascript like this:
x.src = "data:image/jpg;base64," + imageData;
And it doesn't work.
If you want a dataURI version of your image, the best way is to set the XHR.responseType to "blob", and read the resulted response blob with a FileReader :
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function(){
var reader = new FileReader();
reader.onload = function(){
img.src = this.result;
result.textContent = this.result;
};
reader.readAsDataURL(this.response);
};
xhr.open('GET', 'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png');
xhr.send();
<img id="img"/>
<p id="result"></p>
Of course, you'll have to make the call to the same origin, or to an open server (such as wikimedia one).
You should convert the image to base64 first.
Try this link
How to convert image into base64 string using javascript

Simulate XHR2 file upload

I have a HTML upload button to send (multiple) files to a server which responds with JSON. Based on that response, my application flow continues.
Now, to test the rest of my code (dependent on the server response), I would like to simulate the file upload so that I do not have to manually select and upload new files on every reload.
Following is a simplified version of my upload method:
uploadToServer: function (file) {
var self = this,
data = new FormData(),
xhr = new XMLHttpRequest();
// When the request has successfully completed.
xhr.onload = function () {
var response = $.parseJSON(this.responseText);
var photo = new App.Models.Photo({
filename: response.filename,
name: response.uuid
});
var photoView = new App.Views.Photo({ model: photo });
$('.photos').append(photoView.render().el);
};
// Send to server, where we can then access it with $_FILES['file].
data.append('file', file);
xhr.open('POST', this.url);
xhr.send(data);
}
The uploadToServer parameter file is a File-object from FileList. And as you can see, my server awaits the file inside of $_FILES['file'].
It would be awesome if a could simulate a real File-object being passed into uploadToServer, since I then do not have to worry about my existing events such as xhr.onload and xhr.onprogress being available.
If that won't be possible, I could create a custom uploadToServer method and send a regular AJAX-request and fake-respond on my server. But how can I then use and bind the code from my events (xhr.onload, xhr.onprogress etc.) to that AJAX-request?
You could simulate a file upload by creating a canvas, converting it to a file and passing the result to your method.
Create a canvas : here, a nice red square
var canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
canvas.width = 100;
canvas.height = 100;
ctx.fillStyle = '#ff0000';
ctx.fillRect(0, 0, 100, 100);
document.body.appendChild(canvas);
Convert it to a file and pass it to your method: I used Canvas to Blob to simplify the test but you probably can extract the bare bones to fit your needs.
canvas.toBlob( function (blob) {
m.uploadToServer(blob);
}, 'image/jpeg');
And a Fiddle http://jsfiddle.net/pvWxx/ Be sure to open a console to see the events and the request.
If you want to pass a filename with your blob, you can pass a third argument to formData.append, see How to give a Blob uploaded as FormData a file name? and an updated Fiddle http://jsfiddle.net/pvWxx/1/

Categories