Upload resized form image to server - javascript

I want to upload a resized image to server, but I get "Required MultipartFile parameter 'file' is not present" error when I try to upload the resized image. When I upload the original file from there is no problem.
Script:
function resizeAndUpload(file) {
var reader = new FileReader();
reader.onloadend = function () {
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function () {
var MAX_WIDTH = 200;
var MAX_HEIGHT = 200;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataURL = canvas.toDataURL("image/jpeg");
var data = new FormData();
data.append('file', dataURL);
$.ajax({
url: '/changeimage',
type: 'POST',
data: data,
cache: false,
contentType: false,
processData: false,
success: function () {
window.alert("uploaded")
}
});
}
}
reader.readAsDataURL(file);
}
Server:
#RequestMapping(value = "/changeimage", method = RequestMethod.POST)
#ResponseBody
public String changeProfileImage(#Context HttpServletRequest request, #RequestParam("file") MultipartFile file) {
return "ok";
}

A data url is a string and will not upload as a file.
However you can use a blob instead
...
ctx.drawImage(this, 0, 0, tempW, tempH);
canvas.toBlob(function(blob){
var data = new FormData();
data.append('file', blob);
$.ajax({
url: '/changeimage',
type: 'POST',
data: data,
cache: false,
contentType: false,
processData: false,
success: function () {
window.alert("uploaded")
}
});
});
...

Related

send canvas as an image to server

Trying to crop image and send canvas as an image to server but original image is sent to server.
Code used is as follows:
<script type="text/javascript">
var crop_max_width = 400;
var crop_max_height = 400;
var jcrop_api;
var canvas;
var context;
var image;
var prefsize;
$("#file").change(function() {
console.log("1");
loadImage(this);
});
function loadImage(input) {
if (input.files && input.files[0]) {
console.log("2");
var reader = new FileReader();
canvas = null;
reader.onload = function(e) {
console.log("3");
image = new Image();
image.onload = validateImage;
/* $("image").on("load",function() {image.src = e.target.result;}); */
image.src = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}
function dataURLtoBlob(dataURL) {
var BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) == -1) {
console.log("4");
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = decodeURIComponent(parts[1]);
return new Blob([raw], {
type: contentType
});
}
console.log("4 else");
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
});
}
function validateImage() {
if (canvas != null) {
console.log("5");
image = new Image();
image.onload = restartJcrop;
image.src = canvas.toDataURL('image/png');
} else restartJcrop();
}
function restartJcrop() {
if (jcrop_api != null) {
console.log("6");
jcrop_api.destroy();
}
console.log("7");
$("#views").empty();
$("#views").append("<canvas id=\"canvas\">");
canvas = $("#canvas")[0];
context = canvas.getContext("2d");
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0);
$("#canvas").Jcrop({
onSelect: selectcanvas,
onRelease: clearcanvas,
boxWidth: crop_max_width,
boxHeight: crop_max_height
}, function() {
console.log("8");
jcrop_api = this;
});
clearcanvas();
}
function clearcanvas() {
console.log("9");
prefsize = {
x: 0,
y: 0,
w: canvas.width,
h: canvas.height,
};
}
function selectcanvas(coords) {
console.log("10");
prefsize = {
x: Math.round(coords.x),
y: Math.round(coords.y),
w: Math.round(coords.w),
h: Math.round(coords.h)
};
}
function applyCrop() {
console.log("11");
canvas.width = prefsize.w;
canvas.height = prefsize.h;
context.drawImage(image, prefsize.x, prefsize.y, prefsize.w, prefsize.h, 0, 0, canvas.width, canvas.height);
validateImage();
}
$("#cropbutton").click(function(e) {
console.log("12");
applyCrop();
});
$("#form").submit(function(e) {
console.log("form clicked for image");
e.preventDefault();
formData = new FormData($(this)[0]);
var blob = dataURLtoBlob(canvas.toDataURL("image/png"));
//---Add file blob to the form data
formData.append("file", blob);
$.ajax({
url: "/uploadImages/",
type: "POST",
data: formData,
contentType: false,
cache: false,
processData: false,
success: function(data) {
console.log("Successfully uploaded");
location.href = "${pageContext.request.contextPath}/myPage/"
},
error: function(data) {
alert("Error");
},
complete: function(data) {}
});
});
</script>
I want to send canvas as an image to server but original image is sent to server.

Reducing the size of image file for faster uploading?

I have a simple code to upload files using ajax to server, but i don't know how i can resize the image before that process to improve the performance ..
Code of Previewing image.
function Preview_Image(index){
var img = document.createElement("img");
img.src = window.URL.createObjectURL(filesList[index]);
$('#loaded-image-frame' + index + ' #preview').html(img);
img.onload = function () {
window.URL.revokeObjectURL(img.src);
}
}
Code of Uploading image..
function Upload_ResizedImage(index){
var image = filesList[index]
var form_data = new FormData();
form_data.append('file[]', image);
process = $.ajax({
url: "ControlPanelAjax.ashx?job=UploadImages,
type: "POST",
data: form_data,
processData: false,
cache: false,
contentType: false,
beforeSend: function (event) { },
success: function (data, textStatus, jQxhr) {
if (data != '-1') {
alert("image uploaded correctly");
}
else {
alert("Error Uploading..");
}
},
complete: function (event) {},
error: function (jqXhr, textStatus, errorThrown) {},
xhr: function () {}
});
}
Note: filesList is an array containing files that i made up
You can achieve this using canvas from HTML5. Here is a tutorial and here is the related code
HTML:
if (window.File && window.FileReader && window.FileList && window.Blob) {
document.getElementById('filesToUpload').onchange = function(){
var files = document.getElementById('filesToUpload').files;
for(var i = 0; i < files.length; i++) {
resizeAndUpload(files[i]);
}
};
} else {
alert('The File APIs are not fully supported in this browser.');
}
function resizeAndUpload(file) {
var reader = new FileReader();
reader.onloadend = function() {
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function() {
var MAX_WIDTH = 400;
var MAX_HEIGHT = 300;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataURL = canvas.toDataURL("image/jpeg");
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(ev){
document.getElementById('filesInfo').innerHTML = 'Done!';
};
xhr.open('POST', 'uploadResized.php', true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
var data = 'image=' + dataURL;
xhr.send(data);
}
}
reader.readAsDataURL(file);
}
PHP:
if ($_POST) {
define('UPLOAD_DIR', 'uploads/');
$img = $_POST['image'];
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.jpg';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
}

Send formData seperatly

Ok this is what I am trying to acchomplish, (As of Now)I have user select image and the image is resized and uploaded to server. What i would like to do is after the image is selected and resized then stop Script. Then i would like to create a function to upload resized image when i choose to. The reason is that i am going to add more inputs texts into my form and was user has finished completing I then want to upload image with the files. Note: I have not added the text inputs will do after just want to be able to sepearate the upload functions..I am not sure how to seperate the FormData post portion
JAVASCRIPT
<script>
function ResizeMe(){
var dataurl = null;
var uniq = 'id' + (new Date()).getTime();
var filesToUpload = document.getElementById('input').files;
var file = filesToUpload[0];
// Create an image
var img = document.createElement("img");
// Create a file reader
var reader = new FileReader();
// Set the image once loaded into file reader
reader.onload = function(e)
{
img.src = e.target.result;
img.onload = function () {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 200;
var MAX_HEIGHT = 400;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
dataurl = canvas.toDataURL("image/jpeg",.2);
var blobBin = atob(dataurl.split(',')[1]);
var array = [];
for(var i = 0; i < blobBin.length; i++) {
array.push(blobBin.charCodeAt(i));
}
var files = new Blob([new Uint8Array(array)], {type: 'image/jpg', name: "ddd"});
// Post the data
var fd = new FormData();
fd.append("image", files, uniq);
$.ajax({
url: 'http:///www.***/upload.php',
data: fd,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
$('#form_input')[0].reset();
location.reload();
}
});
} // img.onload
}
// Load files into file reader
reader.readAsDataURL(file);
}
</script>
The code sending the formdata is
$.ajax({
url: 'http:///www.***/upload.php',
data: fd,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
$('#form_input')[0].reset();
location.reload();
}
});
That code is the code that you will want to put in a separate function. To move it elsewhere, you have to make sure it still has access to all of the variables being sent, namely, fd. fd is connected to several variables, all leading back to canvas. You say that there will only be one canvas at a time, so we can make canvas a global variable, and then getting fd from anywhere will be easy.
<script>
//Moved to global so that sendFormStuff will see it
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
function ResizeMe(){
var dataurl = null;
var uniq = 'id' + (new Date()).getTime();
var filesToUpload = document.getElementById('input').files;
var file = filesToUpload[0];
// Create an image
var img = document.createElement("img");
// Create a file reader
var reader = new FileReader();
// Set the image once loaded into file reader
reader.onload = function(e)
{
img.src = e.target.result;
img.onload = function () {
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 200;
var MAX_HEIGHT = 400;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
} // img.onload
}
function sendFormStuff() {
var dataurl = canvas.toDataURL("image/jpeg",.2);
var blobBin = atob(dataurl.split(',')[1]);
var array = [];
for(var i = 0; i < blobBin.length; i++) {
array.push(blobBin.charCodeAt(i));
}
var files = new Blob([new Uint8Array(array)], {type: 'image/jpg', name: "ddd"});
// Post the data
var fd = new FormData();
fd.append("image", files, uniq);
$.ajax({
url: 'http:///www.***/upload.php',
data: fd,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
$('#form_input')[0].reset();
location.reload();
}
});
}
// Load files into file reader
reader.readAsDataURL(file);
}
</script>
So really all we did here was move the request code into a separate function, and make canvas and ctx (which you were declaring twice, btw) accessible by that function.

jQuery Ajax: set dataUrl beforeSend

This AJAX request doesn't return any 64-Value-String in the beforeSend handler like it should. But as alert in the function it does! I don't know how to do this async. What is the Issue?
$imageMaps[0] = '1.jpeg';
$imageMaps[1] = '2.jpeg';
for (var k in $imageMaps) {
$file = $imageMaps[k];
$.ajax({
type: "POST",
async: 0,
beforeSend: function (xhr, settings) {
$base64 = convertImgToBase64($file);
alert($base64)
settings.data.img = $base64;
settings.data.url = $file;
},
url: '/request.php?imagePost=1',
data: {
img: '',
url: $file
},
success: function () {}
});
}
function convertImgToBase64(url) {
var img = new Image();
img.src = url;
img.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);
dataurl = canvas.toDataURL("image/png");
alert(dataurl)
return dataurl;
}
}
You are actually returning nothing from that func. Try to do like this:
function convertImgToBase64(url) {
var img = new Image();
img.src = url;
return img.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);
dataurl = canvas.toDataURL("image/png");
alert(dataurl)
return dataurl;
}
}
I may be wrong, so if does not work, do comment it.
Here is the Solution:
$imageMaps[0] = '1.jpeg';
$imageMaps[1] = '2.jpeg';
for (var k in $imageMaps) {
$file=$imageMaps[k];
convertImgToBase64($url, function($base64Img,$url2){
$.ajax({
type: "POST",
async : 1,
url: '/request.php?imagePost=1',
data: {img:$base64Img,url:$url2},
xhr: function() {},
success: function(){}
});
})
}
function convertImgToBase64(url, callback, outputFormat){
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this,0,0);
var dataURL = canvas.toDataURL(outputFormat || 'image/png');
callback(dataURL,url);
canvas = null;
};
img.src = url;
}

How to create an image file from a dataURL?

I am trying to upload pictures to Parse.com, I do not have the files, but the dataURL's (because I resized the images), but need an image file to upload.
Any tip is welcome.
Here is the code for further details:
// First want to resize the image, where the result is a dataURL
var dataURL;
function resizePicture(file) { // This file is the original image
var reader = new FileReader();
reader.onloadend = function() {
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function() {
var MAX_WIDTH = 100;
var MAX_HEIGHT = 150;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0, tempW, tempH);
dataURL = canvas.toDataURL("image/jpeg"); // How can I convert this dataURL to an image file?
}
}
reader.readAsDataURL(file);
}
// Then, want to upload the image to Parse.com.
function savePicture() {
var name = "productPicture.jpg";
var parseFile = new Parse.File(name, dataURL); // Here instead of dataURL, I need an image file.
parseFile.save().then(function() {
// successful save
}, function(error) {
alert("The file either could not be read, or could not be saved to Parse.");
});
}
As per the API Documentation for Parse.File(name, data, type):
data
The data for the file, as either:
an Array of byte value Numbers, or
an Object like { base64: "..." } with a base64-encoded String.
a File object selected with a file upload control.
(3) only works in Firefox 3.6+, Safari 6.0.2+, Chrome 7+, and IE 10+.
In theory this should work:
// get everything after "base64,"
var base64 = dataURL.split('base64,')[1];
var parseFile = new Parse.File(name, { base64: base64 });

Categories