i am using cropperjs to crop images
Using the method getCroppedCanvas to get reference to the cropped canvas image
Using the canvas method canvas.toDataURL to compress the images into a jpeg files.
I don't use canvas.toBlob as its browser support is not clear.
My question is how can i turn the string i get from canvas.toDataURL into a blob so i can later use it in formData.
Update
server expect form data - multi-part
One method that I used while working on some tool is to convert the dataURL to Blob using this function:
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
And then you can send the Blob to the server using native xhr like this:
var blob = dataURLtoBlob(dataURI);
var fd = new FormData();
var xhr = new XMLHttpRequest ();
fd.append ('file', blob);
xhr.open('POST', '/endpoint', true);
xhr.onerror = function () {
console.log('error');
}
xhr.onload = function () {
console.log('success')
}
xhr.send (fd);
The blob builder code is taken from here: https://stackoverflow.com/a/30407840/2386736
use canvas.toDataURL to generate an JPEG image:
var JPEG_QUALITY=0.5;
var dataUrl = canvas.toDataURL('image/jpeg', JPEG_QUALITY).replace('data:image/jpeg;base64,', '');
And then send it to AJAX as data-multi-part:
jQuery.ajax({
url: 'php/upload.php',
data: dataUrl,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
}
});
Depending on what your server side expects to receive.
By the way: You wrote "I don't use canvas.toBlob as its browser support is not clear" - You can see the browser support here:
Related
I have two audio files from RecordRTC both local & remote streams. Now I want to merge the two files into one file and upload it to the server via AJAX.
e.g. (audio1.webm) and (audio2.webm).
mediaRecorder.stopRecording(function() {
var blob = mediaRecorder.getBlob();
var fileName = getFileName('webm');
var fileObject = new File([blob], fileName, {
type: 'audio/webm'
});
var formData = new FormData();
formData.append('blob', fileObject);
formData.append('filename', fileObject.name);
$.ajax({
url: '{{ url('/') }}/save-audio',
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(response) {
console.log(response);
}
});
});
Thank you in advance.
UPDATE:
I made it this way instead of recorder.addStreams, and still I can get the recorded.
var remoteVideos = $('#remoteVideos video');
var el = [];
$.each($('#remoteVideos video'), function(index, val) {
el[index] = val.srcObject;
});
el.push(stream);
multiMediaRecorder = new MultiStreamRecorder(el);
You can use a similar library: MediaStreamRecorder. Then use MultiStreamRecorder and pass two streams as below,
recorder = new MultiStreamRecorder([localStream, remoteStream]);
You will get localStream from getUserMedia and remoteStream from onaddstream event listener.
You may want to just pass the audio tracks in the array. The rest of the things as it is. FFmpeg and file merging is not necessary.
I got it now by doing this, as below;
function onMediaSuccess(localStream) {
var remoteVideos = $('#remoteVideos video')[0];
multiMediaRecorder = new MultiStreamRecorder([localStream, remoteVideos.srcObject]);
multiMediaRecorder.ondataavailable = function (blob) {
// POST/PUT "Blob" using FormData/XHR2
var blobURL = URL.createObjectURL(blob);
console.log(blobURL);
};
multiMediaRecorder.start();
}
But now there's another problem, ondataavailable is called twice but the first video is playable and working properly, while the second video is playable but (less than one second) I think it might be corrupted.
Cheers!
I need to send an image from client to server using blob
I have converted a image to BLOB in jquery (client side) and sending the blob to python flask (server side) the problem is, I can't recreate image from BLOB. I have tried the following code in python but failed to get the image
Jquery code to convert image to blob:
function changeFile() {
var file = this.files[0];
var reader = new FileReader();
reader.addEventListener('load', readFile);
reader.readAsText(file);
}
function readFile(event) {
document.body.textContent = event.target.result;
console.log(event.target.result);
appendFileAndSubmit(event.target.result);
}
function appendFileAndSubmit(imageUrl){
var ImageURL = imageUrl
var data = {
'logo':ImageURL
}
$.ajax({
url: 'http://sdsdss/User/imgBlob',
method: 'POST',
dataType : 'json',
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8'
}).done(function(response){
var datas = JSON.parse(response);
console.log(datas);
});
}
document.getElementById("inp").addEventListener("change", changeFile);
Python Code: To recreate BLOB to image
function getImage(self):
reqData = json.loads(request.data)
Logo = reqData['logo']
png_recovered = base64.decodestring(Logo)
f = open("temp.png", "w")
f.write(png_recovered)
f.close()
Don't read the file as text, You are dealing with binary data. Best way to transfer binary with json is if you read the file as base64 instead reader.readAsDataURL(file) This will encode all bytes to a web safe base64 string (no slash or plus). Then you have to decode it with python as well.
I discourage you from using json when dealing with file transfer as it will increase the bandwidth with ~3 times as much (not to mention the time it also takes to decode and encode it back and forth) For this I recommend you instead use FormData.
var fd = new FormData()
fd.append('logo', files[0])
$.ajax({
url: 'http://sdsdss/User/imgBlob',
method: 'POST',
data: fd,
// Setting false prevent jQuery from transforming the data
processData: false,
contentType: false
}).then(function(response) {
console.log(JSON.parse(response))
})
or simpler yet, just post the file without any formdata, json or extra fields if they are not necessary.
fetch(uploudUrl, { method 'PUT', body: this.files[0] })
I need help with HTML canvas element.I'm new to HTML.
I need to capture image from the webcam and send it to Microsoft cognitive API to find the emotions in the picture.
The API accepts image in octet-stream. The API is https://westus.dev.cognitive.microsoft.com/docs/services/5639d931ca73072154c1ce89/operations/563b31ea778daf121cc3a5fa
The code is
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext('2d');
dataUrl = canvas.toDataURL("image/png");
$.ajax({
url: apiUrl,
beforeSend: function(xhrObj) {
xhrObj.setRequestHeader("Content-Type", "application/octet-stream");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", apiKey);
},
type: "POST",
data: dataUrl,
processData: false
}).done(function(response) {
...
});
HTTP Response code is 400 and the response message is as below.
{"error":{"code":"BadBody","message":"Invalid face image."}}
logging the dataUrl shows the data as
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAgAElEQVR4XqS92bOm2Vnlt7/pZGZVCU3IGkFCDhoxChDQBknQtGUBJtzd4Vvf+a7RUFklqVQC/xu.....
I have tried by removing data:image/png but no use.
I'm right canvas.toDataURL returns string form of base64 encoded data of the image. I can display this image on html page. I also did a right click saved it to local drive, and called API with file, it works.
So, the issue would be while moving the data from canvas element to the request body in binary format.
How can this be done ?. Thanks in advance for your help.
This might work. Try creating Blob from your dataUrl and pass it in to the ajax, as:
function createBlob(dataURL) {
var BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = decodeURIComponent(parts[1]);
return new Blob([raw], { type: contentType });
}
var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
in ajax, pass the blobData,
...
var blobData = createBlob(dataUrl);
$.ajax({
url : apiUrl,
beforeSend : function(xhrObj) {
xhrObj.setRequestHeader("Content-Type", "application/octet-stream");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", apiKey);
},
type : "POST",
data : blobData,
processData : false
}).done(function(response) {...}
I am attempting to send image data to a server API, though, the documentation included with the API only contains an example for JQuery, which I don't want to use with my nodejs project. Also, the JQuery example contains things that don't exist in Node, such as Blobs.
The example provided by the API is:
var sourceImage = new Image();
sourceImage.src = image; // add image data to object
sourceImage.onload = function() {
// Create a canvas with the desired dimensions
var canvas = document.createElement("canvas");
var dim = 256; // the image size
canvas.width = dim;
canvas.height = dim;
// Scale and draw the source image to the canvas
canvas.getContext("2d").drawImage(sourceImage, 0, 0, dim, dim);
var formDataWithCanvasImage = createFormData(canvas);
// Make ajax call here
}
function createFormData(canvas) {
var b64Img = canvas.toDataURL();
var binImg = dataURItoBlob(b64Img);
var fileName = new Date().getTime();// Name the file with the current timestamp and no extension
var fd = new FormData();
fd.append("imageClass", "preview");
fd.append("X-Requested-With", "Iframe");
fd.append("X-HTTP-Accept", "application/json, text/javascript, */*; q=0.01");
fd.append("file", binImg,fileName);
return fd;
}
$.ajax({
url: imageURL,
data: formDataWithCanvasImage,
processData: false,
contentType: false,
type: 'POST',
error: function() {alert("error uploading image");},
success: function(data){
console.log(data);
}
});
However, this wouldn't work with nodejs, because there is no canvas in nodejs, and no such thing as a blob. So, what I've done is read an image from the local disc and convert that buffer into an ArrayBuffer then encode it in analog-nico's request-promise like so:
let opts = {
uri: 'https://*****.com/api/images',
contentType: false,
processData: false,
type: 'POST',
formData: {
"imageClass": "application",
"X-Requested-With": "Iframe",
"X-HTTP-Accept": "application/json, text/javascript, */*; q=0.01"
"file": arraybuffer
},
}
request.post(opts).then(data => {....});
but the code throws TypeError: source.on is not a function. Has anyone encountered this problem before? How did you resolve it?
You could try loading the image from disk as a ReadStream and piping that using the request module to the API.
Rough Example:
fs.createReadStream(filename).pipe(request.put('http://example.com/api/images'))
The module is available via npm install request.
I'd like to build a simple HTML page that includes JavaScript to perform a form POST with image data that is embedded in the HTML vs a file off disk.
I've looked at this post which would work with regular form data but I'm stumped on the image data.
JavaScript post request like a form submit
** UPDATE ** Feb. 2014 **
New and improved version available as a jQuery plugin:
https://github.com/CoeJoder/jquery.image.blob
Usage:
$('img').imageBlob().ajax('/upload', {
complete: function(jqXHR, textStatus) { console.log(textStatus); }
});
Requirements
the canvas element (HTML 5)
FormData
XMLHttpRequest.send(:FormData)
Blob constructor
Uint8Array
atob(), escape()
Thus the browser requirements are:
Chrome: 20+
Firefox: 13+
Internet Explorer: 10+
Opera: 12.5+
Safari: 6+
Note: The images must be of the same-origin as your JavaScript, or else the browser security policy will prevent calls to canvas.toDataURL() (for more details, see this SO question: Why does canvas.toDataURL() throw a security exception?). A proxy server can be used to circumvent this limitation via response header injection, as described in the answers to that post.
Here is a jsfiddle of the below code. It should throw an error message, because it's not submitting to a real URL ('/some/url'). Use firebug or a similar tool to inspect the request data and verify that the image is serialized as form data (click "Run" after the page loads):
Example Markup
<img id="someImage" src="../img/logo.png"/>
The JavaScript
(function() {
// access the raw image data
var img = document.getElementById('someImage');
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
var dataUrl = canvas.toDataURL('image/png');
var blob = dataUriToBlob(dataUrl);
// submit as a multipart form, along with any other data
var form = new FormData();
var xhr = new XMLHttpRequest();
xhr.open('POST', '/some/url', true); // plug-in desired URL
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
alert('Success: ' + xhr.responseText);
} else {
alert('Error submitting image: ' + xhr.status);
}
}
};
form.append('param1', 'value1');
form.append('param2', 'value2');
form.append('theFile', blob);
xhr.send(form);
function dataUriToBlob(dataURI) {
// serialize the base64/URLEncoded data
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURI.split(',')[1]);
}
else {
byteString = unescape(dataURI.split(',')[1]);
}
// parse the mime type
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// construct a Blob of the image data
var array = [];
for(var i = 0; i < byteString.length; i++) {
array.push(byteString.charCodeAt(i));
}
return new Blob(
[new Uint8Array(array)],
{type: mimeString}
);
}
})();
References
SO: 'Convert DataURI to File and append to FormData
Assuming that you are talking about embedded image data like http://en.wikipedia.org/wiki/Data_URI_scheme#HTML
****If my assumption is incorrect, please ignore this answer.**
You can send it as JSON using XMLHttpRequest.
Here is sample code: (you may want to remove the header part ('data:image/png;base64,') before sending)
Image
<img id="myimg" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
Button
<input id="subbtn" type="button" value="sub" onclick="sendImg()"></input>
Script
function sendImg() {
var dt = document.getElementById("myimg").src;
var xhr = new XMLHttpRequest();
xhr.open("POST", '/Home/Index', true); //put your URL instead of '/Home/Index'
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) { //4 means request finished and response is ready
alert(xhr.responseText);
}
};
var contentType = "application/json";
xhr.setRequestHeader("Content-Type", contentType);
for (var header in this.headers) {
xhr.setRequestHeader(header, headers[header]);
}
// here's our data variable that we talked about earlier
var data = JSON.stringify({ src: dt });
// finally send the request as binary data
xhr.send(data);
}
EDIT
As #JoeCoder suggests, instead of json, you can also use a FormData object and send in Binary format. Check his answer for more details.