I have an interface that allows multiple file uploads. The user dumps a set of files on the file element.
The script then sets the height, width and dpi of those images and displays them in a large thumbnail.
That all works fine. If I right-click and save an image, it is now 1600x1600 at 96 dpi. Exactly what I specified.
Now, I need to upload the images through AJAX by creating a new FileList. But how do I specify the filename and the content for the file list?
I have a hidden file element which I'll update with the new file list which will trigger the AJAX.
Here is the HTML and the javascript/jquery:
<form enctype="multipart/form-data" id="frmUploadImage">
<input name="files" type="file" id="imgUpload" class="upload" multiple accept="image/*"/>
</form>
<form enctype="multipart/form-data" id="frmSaveImage" style="display:none">
<input name="files" type="file" id="saveImages" class="upload" multiple accept="image/*"/>
</form>
<input type="button" id="saveIt" value="Save">
<script>
$(`#imgUpload`).on(`change`, function() {
const $fileUpload = $(this);
Array.from($fileUpload.get(0).files).forEach(function(f, i) {
$(`#compressResultsContainer`).append(`<div id="image_${i}_container" class="compressedImageContainer"><img id="source_${i}" style="display:none"/><img id="image_${i}" class="compressedImage" style="width: 200px; height:200px"/><canvas id="canvas_${i}" style="display:none"></canvas><div>`);
let $preview = $(`#source_${i}`);
var reader = new FileReader();
reader.addEventListener(`load`, function(e) {
$preview.attr(`src`, e.target.result);
$preview.on(`load`, function() {
console.log(`loading preview ${i}`);
compressFile(this, i);
});
}, false);
if (f) {
reader.readAsDataURL(f);
}
});
});
function compressFile(loadedData, imgNum) {
var mime_type = `image/jpeg`;
var cvs = document.getElementById(`canvas_${imgNum}`);
cvs.width = 1600;
cvs.height = 1600;
var ctx = cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 1600,1600);
var newImageData = cvs.toDataURL(mime_type, 96);
var result_image_obj = new Image();
result_image_obj.src = newImageData;
$(`#image_${imgNum}`).attr(`src`, result_image_obj.src);
}
// my test function just to see if I can build new form data---
$(`#saveIt`).on(`click`, function() {
let formData = new FormData();
$(`.newCanvas`).each(function() {
let file;
const canvas =document.getElementById($(this).attr(`id`));
canvas.toBlob((blob) => {
console.log(`canvas:`, $(this).attr(`id`));
file = new File([blob], $(this).attr(`filename`), { type: `image/jpeg` });
formData.append(`savedImages`, new File([blob], $(this).attr(`filename`), { type: `image/jpeg` }));
console.log(file);
}, `image/jpeg`);
});
setTimeout(function() { console.log(formData); }, 3000);
});
</script>
I'm basically stuck on how to populate the new FileList with the proper content -- the compressed images and their filename.
You had ONE tiny issue which made nothing to work: looping through the .newCanvas elements when absolutely no element had the class. So the loop squarely didn't run.
There also is a couple "improvements" that can be done... But to have the formData populated, that was the only thing.
So I added class="newCanvas" to <canvas id="canvas_${i}" on that line:
$(`#compressResultsContainer`).append(
`<div id="image_${i}_container" class="compressedImageContainer"><img id="source_${i}" style="display:none"/><img id="image_${i}" class="compressedImage" style="width: 200px; height:200px"/><canvas id="canvas_${i}" class="newCanvas" data-name="${f.name}" style="display:none"></canvas><div>`
);
Notice that I also added a data-name to hold the file name. That information has to be carried by the canvas to later be usable in the .each() loop.
Now about a couple improvements:
You use backticks everywhere. Good practice would be to use them when really needed, like when some templating ${variable} is inside the string...
document.getElementById($(this).attr(id)) is EXACTLY the same as just this.
Except that you've made a jQuery lookup on this to get the id and then used that id to retreive the element using plain JS.
In an .each() loop, this is the element of the current loop.
Within the .toBlob() callback, $(this) no longer is the canvas element. You have to get the informations from the canvas before calling .toBlob()
You used a setTimeout() to wait for the canvas.toblob() results... That is not reliable. I suggest you to use the number of appended files in the formData and compare that with the number of .newCanvas element to process.
That comparison has to be in the canvas.toblob() callback.
So here is the code I suggest you to try.
$(`#imgUpload`).on(`change`, function () {
const $fileUpload = $(this);
Array.from($fileUpload.get(0).files).forEach(function (f, i) {
$(`#compressResultsContainer`).append(
`<div id="image_${i}_container" class="compressedImageContainer"><img id="source_${i}" style="display:none"/><img id="image_${i}" class="compressedImage" style="width: 200px; height:200px"/><canvas id="canvas_${i}" class="newCanvas" data-name="${f.name}" style="display:none"></canvas><div>`
);
let $preview = $(`#source_${i}`);
var reader = new FileReader();
reader.addEventListener(
`load`,
function (e) {
$preview.attr(`src`, e.target.result);
$preview.on(`load`, function () {
console.log(`loading preview ${i}`);
compressFile(this, i);
});
},
false
);
if (f) {
reader.readAsDataURL(f);
}
});
});
function compressFile(loadedData, imgNum) {
var mime_type = `image/jpeg`;
var cvs = document.getElementById(`canvas_${imgNum}`);
cvs.width = 1600;
cvs.height = 1600;
var ctx = cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 1600, 1600);
var newImageData = cvs.toDataURL(mime_type, 96);
var result_image_obj = new Image();
result_image_obj.src = newImageData;
$(`#image_${imgNum}`).attr(`src`, result_image_obj.src);
}
// my test function just to see if I can build new form data---
$(`#saveIt`).on(`click`, function () {
let allCanvas = $(`.newCanvas`)
let canvasCount = allCanvas.length
let formData = new FormData();
allCanvas.each(function () {
let file;
const canvas = this // document.getElementById($(this).attr(`id`));
// Get the filename here
// Because inside the .toBlob callback this and $(this) no longer is the canvas
let canvasName = this.getAttribute("data-name")
canvas.toBlob((blob) => {
console.log(`canvas:`, $(this).attr(`id`));
file = new File([blob], canvasName, { type: `image/jpeg` });
formData.append(
`savedImages`,
file
);
console.log(file);
// Did we procces all canvas?
// This part is to replce your setTimeout
// So here you can call the Ajax
if(formData.getAll("savedImages").length === canvasCount){
// Just formData will print the constructor
//console.log(formData);
console.log(formData.getAll("savedImages"));
}
}, `image/jpeg`);
});
/*
setTimeout(function () {
console.log(formData);
}, 3000);
*/
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form enctype="multipart/form-data" id="frmUploadImage">
<input name="files" type="file" id="imgUpload" class="upload" multiple accept="image/*" />
</form>
<form enctype="multipart/form-data" id="frmSaveImage" style="display:none">
<input name="files" type="file" id="saveImages" class="upload" multiple accept="image/*" />
</form>
<input type="button" id="saveIt" value="Save">
<div id="compressResultsContainer"></div>
I finally had time to get back to this yesterday. This works:
<h1>Image Maintenance</h1><br>
<input name="files" type="file" id="imgProcess" class="upload" multiple accept="image/*"/>
<div id="progressContainer">
<div id="processProgressContainer">
<progress id="processProgress" value="0" style="vertical-align: middle;"></progress>
<span id="processStatus" style="margin-left: 20px;"></span>
</div>
<div id="uploadProgressContainer" style="display:none">
<span style="width: 150px; float:left">Seasonal Upload</span>
<span style="width: 150px; float:left">.Com Upload</span>
<span style="width: 150px; float:left">Repository Upload</span><br style="clear:both"/>
<span style="width: 150px; float:left"><progress id="seasonalProgress" value="0" style="vertical-align: middle;"></progress></span>
<span style="width: 150px; float:left"><progress id="comProgress" value="0" style="vertical-align: middle;"></progress></span>
<span style="width: 150px; float:left"><progress id="repositoryProgress" value="0" style="vertical-align: middle;"></progress></span>
</div>
</div>
<input type="button" id="saveIt" value="Save">
<input type='text' class='chromeAutoInputCatcher' tabindex='-1' name='stupidChromeInputCatcher'></input>
<div id="compressResultsContainer"></div>
<script>
// #ts-nocheck
/* eslint-disable no-undef */
/* eslint-disable max-len */
/* eslint-disable no-invalid-this */
/* eslint-disable require-jsdoc */
/* jshint esversion: 8 */
let kpData;
let repositoryData;
let collection = `524`;
let skuString = `,`;
$(`#imgProcess`).on(`change`, function() {
$(`#uploadProgressContainer`).hide();
$(`#processProgressContainer`).show();
$(`#processProgress`).val(0);
kpData = new FormData();
repositoryData = new FormData();
let rootsku=``;
skuString = `,`;
$(`#compressResultsContainer`).html(``);
//at some point, let's freeze all input until we get done compressing and displaying
const $fileUpload = $(this);
const numPics = $fileUpload.get(0).files.length;
$(`#processProgress`).attr(`max`, numPics);
Array.from($fileUpload.get(0).files).every(f=> {
const thisSku = f.name.split(`-`).slice(0, 4).join(`-`);
if (!rootsku.length) {
rootsku = thisSku.split(`-`)[0];
}
const thisrootsku = thisSku.split(`-`)[0];
if (rootsku !== thisrootsku) {
alert(`found multiple root skus. Aborting`);
$(`#imgProcess`).val(``);
kpData = new FormData();
repositoryData = new FormData();
return false;
}
return true;
});
Array.from($fileUpload.get(0).files).forEach(function(f, i) {
const thisSku = f.name.split(`-`).slice(0, 4).join(`-`);
if (skuString.indexOf(thisSku) < 0) {
skuString += `${thisSku},`;
}
$(`#compressResultsContainer`).append(`<div id="image_${i}_container" class="compressedImageContainer"><img id="source_${i}" style="display:none"/><img id="image_${i}" filename="${f.name}" class="compressedImage" style="width: 200px; height:200px; float:left"/><canvas class="newCanvas" id="canvas_${i}" style="display:none" filename="${f.name}"></canvas><span style="float:left">${f.name}</span></div><br style="clear:both"/>`);
let $preview = $(`#source_${i}`);
var reader = new FileReader();
reader.addEventListener(`load`, function(e) {
$preview.attr(`src`, e.target.result);
$preview.on(`load`, function() {
createImages(this, i);
$(`#processProgress`).val($(`#processProgress`).val() + 1);
$(`#processStatus`).html(`${$(`#processProgress`).val()} of ${numPics} file: ${f.name} `).attr(`filenum`, $(`#processProgress`).val());
if ($(`#processProgress`).val() === numPics) {
getSkus(rootsku);
console.log(`done processing`);
}
});
}, false);
if (f) {
reader.readAsDataURL(f);
}
});
});
function createImages(loadedData, imgNum) {
var mime_type = `image/jpeg`;
var cvs = document.getElementById(`canvas_${imgNum}`);
var cvsName = cvs.getAttribute(`filename`);
//Create the detail version of the image
cvs.width = 800;
cvs.height = 800;
cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 800, 800);
//display the image
var newImageData = cvs.toDataURL(mime_type);
var result_image_obj = new Image();
result_image_obj.src = newImageData;
$(`#image_${imgNum}`).attr(`src`, result_image_obj.src);
//convert the canvase to an uploadable file and append it to our form data
cvs.toBlob((blob) => {
let file = new File([blob], cvsName, { type: `image/jpeg` });
kpData.append(`detail`, file, cvsName);
}, `image/jpeg`,0.96);
//create the general image
cvs.width = 370;
cvs.height = 370;
cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 370, 370);
cvs.toDataURL(mime_type);
cvs.toBlob((blob) => {
let file = new File([blob], cvsName, { type: `image/jpeg` });
kpData.append(`general`, file, cvsName);
}, `image/jpeg`,0.96);
//create the thumbnail
cvs.width = 240;
cvs.height = 240;
cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 240, 240);
cvs.toDataURL(mime_type);
cvs.toBlob((blob) => {
let file = new File([blob], cvsName, { type: `image/jpeg` });
kpData.append(`thumb`, file, cvsName);
}, `image/jpeg`,0.96);
//create the repository image for Amazon, Zulilly, Zappos and our wholesale customers. Zullily has the greatest minimum requirements so we'll use those for everyone
cvs.width = 1600;
cvs.height = 1600;
cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 1600, 1600);
cvs.toDataURL(mime_type);
cvs.toBlob((blob) => {
let file = new File([blob], cvsName, { type: `image/jpeg` });
repositoryData.append(`imgfiles`, file, cvsName);
}, `image/jpeg`, 1);
}
let uploadLocation = `/${scPcFolder}/pc/catalog/`;
saveImages = function(url, formData,server) {
data = formData;
$(`#${server}Progress`).val(0);
$.ajax({
url: url,
cache: false,
contentType: false,
processData: false,
enctype: `multipart/form-data`,
data: data,
type: `POST`,
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener(`progress`, function(e) {
if (e.lengthComputable) {
$(`#${server}Progress`).attr({
value: e.loaded,
max: e.total,
});
}
}, false);
}
return myXhr;
}
}).done(function(data) {
}).fail(function(xhr, textStatus, errorThrown) {
console.log(xhr, textStatus, errorThrown);
}).always(function() {
});
};
function parseReturn(data = ``, nonJson = { beforeData: ``, afterData: `` }) {
data = data.replace(new RegExp(`\r?\n`, `g`), ``).replace(/\t/g, ``);//.replace(/'/g, `''`);
nonJson.beforeData = data.substring(0, data.indexOf(`{`));
nonJson.afterData = data.substring(data.lastIndexOf(`}`) + 1, 99999999);
data = data.substring(data.indexOf(`{`), data.lastIndexOf(`}`) + 1);
try {
return JSON.parse(data);
} catch (e) {
console.log(`error: `, e);
console.log(data);
}
}
$(`#saveIt`).on(`click`, function() {
$(`#processProgressContainer`).hide();
$(`#uploadProgressContainer`).show();
saveImages(`ImageManagement_AJAX.asp?action=saveFiles&uploadLocation=${uploadLocation}&skuString=${skuString}&collection=${collection}`, kpData,`seasonal`);
saveImages(`https://example.com/uploadify/ImageManagement_AJAX.asp?action=saveFiles&uploadLocation=${uploadLocation}`, kpData,`com`);
saveImages(`https://example.com/Image/Upload`, repositoryData,`repository`);
});
function getSkus(rootsku) {
$.ajax({
url: `ImageManagement_AJAX.asp`,
data: { action: `getSkus`, rootsku: rootsku, collection: collection },
type: `POST`,
}).done(function(data) {
//console.log(`data`, data);
let objSkus = parseReturn(data);
objSkus.skus.forEach(function(s) {
s.sku=s.sku.split(`-`).slice(0, s.sku.split(`-`).length - 1).join(`-`);
});
let uniqueSkus = [...new Set(objSkus.skus.map((sku) => sku.sku))];
let html=``;
//make sure every sku has a primary image in this batch of files
uniqueSkus.forEach(function(s) {
if (!$(`.compressedImage[filename="${s}.jpg"]`).length) {
html += `<span style="float:left">${s}</span><span style="float:left; min-width:10px"> </span>`;
console.log(`missing file: `, s);
}
});
if (!html.length) {
html = `Success`;
} else {
html += `<br style="clear:both"/><br/>`;
}
$(`#processStatus`).html(html);
$(`#imgProcess`).val(``);
}).fail(function(xhr, textStatus, errorThrown) {
console.log(xhr, textStatus, errorThrown);
}).always(function() {
});
}
</script>
I have a working file upload with progress bar and the file is uploaded in fileUpload.php.
function fileSelected() {
var file = document.getElementById('fileToUpload').files[0];
if (file) {
var fileSize = 0;
if (file.size > 1024 * 1024)
fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
else
fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
document.getElementById('file-size').innerHTML = fileSize;
}
}
function uploadFile() {
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("POST", "src/fileUpload.php");
xhr.send(fd);
}
function uploadProgress(evt) {
if (evt.lengthComputable) {
var percentComplete = Math.round(evt.loaded * 100 / evt.total);
//var loaded = 0;
if (evt.loaded > 1024 * 1024)
loaded = (Math.round(evt.loaded * 100 / (1024 * 1024)) / 100).toString() + 'MB';
else
loaded = (Math.round(evt.loaded * 100 / 1024) / 100).toString() + 'KB';
document.getElementById('procent').innerHTML = percentComplete.toString() + '%';
document.getElementById('progressNumber').style.width = percentComplete.toString() + '%';
document.getElementById('loaded').innerHTML = loaded.toString();
}
else {
document.getElementById('progressNumber').innerHTML = 'unable to compute';
}
}
HTML:
<form id="order-form" class="needs-validation" method="post" enctype="multipart/form-data" novalidate>
<!-- Lot of inpup forms -->
<div class="custom-file">
<input type="file" class="custom-file-input" id="fileToUpload" onchange="fileSelected();" name="fileToUpload" accept=".zip" required>
<span id="selected-file" class="custom-file-label" for="fileToUpload">Choose file</span>
<div class="invalid-feedback">
Please select a file.
</div>
</div>
<button id="send-button" class="btn btn-primary btn-lg btn-block" type="button" onclick="sendOrder()">Send order</button>
But I alos want to submit the form data to a file sendOrder.php
Right now I have this
function sendOrder() {
$.ajax({
type: 'post',
url: 'src/sendOrder.php',
data: $('form').serialize(),
success: function () {
}
});
uploadFile();
}
But cant I modify my fileupload (first code block) to also send the form data do sendOrder.php?
sendorder.php contains variables like this
$email = $_POST['email'];
And send the information with mail in sendOrder.php with the variables (it is like a contact form).
You should use one ajax call for this.
Change your submit button type to type='submit' and remove the onclick() attribute
$('#order-form').submit(function(e){
e.preventDefault();
var formData = new FormData(this);
$.ajax({
type: 'post',
url: 'src/sendOrder.php',
data: formData,
success: function (response) {
console.log(response);
}
});
})
I am trying to make a Progress Bar for the uploaded progress in my application. So far I have this
<div class="col-sm-12">
<span style="border-left:5px solid #555555; padding-left:.5em">Upload File</span>
<div style="margin-top:1em; margin-left:.8em;">
<input type="file" name="file" class="inputfile" id="group-agent-file" accept=".csv"/>
<label for="file" id="span-file-upload" class="btn btn-danger">
<span class="fa fa-upload" style="margin-right:.5em"></span>
<span id="span-file-name">Choose a file</span>
</label>
<div>
<button type="button" id="btn-group-agent-upload" class="btn btn-primary" title="Upload">Upload</button>
</div>
<div class="progress">
<div class="progress-bar progress-bar-green" role="progressbar" id="progress-bar-upload">
<span></span>
</div>
</div>
and this is my javascript
var result = event.target.result;
var data = $.csv.toObjects(result);
var length = data.length;
var count = 0;
var percent;
$.each(data, function (key, val) {
$.ajax({
xhr: function(){
var xhr = $.ajaxSettings.xhr();
xhr.upload.onprogress = function (evt) {
console.log('progress', evt.loaded / evt.total * 100);
};
},
type: "POST",
url: "IROA_StoredProcedures.asmx/Insert_Bulk_Agent",
data: JSON.stringify(val),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
count = count + 1;
percent = count / length * 100;
$("#progress-bar-upload").css("width", percent + "%");
$("#progress-bar-upload span").text(percent + "% Complete");
console.log("Finished " + count + " of " + length + " employees.");
},
error: function (XMLHttpRequest) {
alert("error in Insert_Bulk_AgentInfo()");
console.log(XMLHttpRequest);
}
});
});
it works fine but I think the html can't process enough that sometimes the width percentage is delayed. How can I do this? and what may be the drawbacks when I use setInterval.
To get upload progress in jQuery you need to attach Event-Listener to the progress event.
You can do something like this in jQuery
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var percentComplete = (evt.loaded / evt.total);
//Update the progress bar
}
});
return xhr;
},
type: 'POST',
url: "/upload/path",
data: { YOUR UPLOAD DATA },
success: function (data) {
}
});
This would work the same for plain js
var xhr = new XMLHttpRequest();
xhr.open('POST', "/upload/path", true);
xhr.upload.addEventListener('progress', function (event) {
if (evt.lengthComputable) {
var percentComplete = (evt.loaded / evt.total);
//Update the progress bar
}
}
xhr.onload = function (response) {
// handle success/error here
}
xhr.setRequestHeader(SET_HEADERS);
xhr.send(UPLOAD_DATA);
success function will be call when your ajax call gets completed.
You should use xhr function instead of success.
xhr: function(){
var xhr = $.ajaxSettings.xhr() ;
xhr.upload.onprogress = function(evt){
console.log('progress', evt.loaded/evt.total*100);
var percentageCompleted = evt.loaded/evt.total*100;
updateUploadPercentage(parseInt(percentageCompleted));
if(percentageCompleted == 100){
$("#p_custom_message_body").html('<p>Storing training data</p><img src="media/images/loading.gif">');
}
} ;
return xhr ;
}
After that update progress bar in another function :-
function updateUploadPercentage(progress) {
var elem = document.getElementById("progressBar");
elem.style.width = progress + '%';
elem.innerHTML = progress * 1 + '%';
}
The requirement:
I am trying preview an image before uploading. So I come up with this code:
function readURL(input)
{
if (input.files && input.files[0])
{
var reader = new FileReader();
reader.onload = function (e) {
$('#preview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
And I am calling the function by this method:
$(document).ready(function(){
$('#image').on('change',function(e){
readURL(this);
});
});
The code is working fine. Now the HTML is this:-
<div class="control-group">
<label class="control-label" for="fileInput"><?php echo ucfirst($entity); ?> Image :</label>
<div class="controls">
<input class="input-file uniform_on" name="image" id="image" type="file"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="fileInput">Image Preview:</label>
<div class="controls">
<img src="#" name="preview" id="preview" height="100" alt="Preview Image"/>
</div>
</div>
Till now the code is running smooth.
Now I want to update my code based on these requirements:-
First the imageSize will be checked, whether it's less than 300KB.
Then it will check if the dimension is less than 1200x1200
If the file is less than 300KB and size less than 1200x1200, then the preview will be displayed.
So I made the following changes:-
var maxImageSize = parseInt(3000) * 100; //3KB * 100 = 300KB
var maxImageWidth = 1200;
var maxImageHeight = 1200;
function readURL(input)
{
if (input.files && input.files[0])
{
var reader = new FileReader();
reader.onload = function (e) {
$('#preview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$(document).ready(function(){
$('#image').on('change',function(e){
var imageSize = this.files[0].size;
if(imageSize > maxImageSize)
{
if(maxImageSize>=1000 && maxImageSize<1000000)
{
var allowedSize = parseFloat(parseInt(maxImageSize)/1000)+' KB';
}
else if(maxImageSize>=1000000)
{
var allowedSize = parseFloat(parseInt(maxImageSize)/1000000)+' MB';
}
var $el = $('#image');
$el.wrap('<form>').closest('form').get(0).reset();
$el.unwrap();
var html = '<strong>Severe Error</strong><p>Max. filesize allowed is '+allowedSize+'</p>';
$('#modalError').html(html);
$('#modalError').show();
$('#modal').modal();
}
else
{
var imgFile = this.files[0];
var img = new Image();
img.src = window.URL.createObjectURL(imgFile);
img.onload = function() {
var imgField = $('#image');
var imgWidth = img.naturalWidth, imgHeight = img.naturalHeight;
if(imgWidth>maxImageWidth && imgHeight>maxImageHeight)
{
var html = '<strong>Severe Error</strong><p>Max. width allowed is '+maxImageWidth+'px & Max. height allowed is '+maxImageHeight+'px</p>';
$('#modalError').html(html);
$('#modalError').show();
$('#modal').modal();
}
else
{
readURL(imgField);
}
};
}
});
});
In the above code, the size and dimension validation is working fine. However, the image is not getting previewed.
What am I doing wrong?
You are passing an <img> to readURL instead of a File object at readURL(imgField)
Trying to upload a photo from my phone to a remote server using phonegap. After compiling when I run the app I got an error message:
Upload failed code = 3.
I read the web and found out there should be an added line of script which I added (
options.chunkedMode = false;
options.headers = {
Connection: "close"
)
Still gets the same error again.
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>PhoneGap</title>
<style type="text/css">
div {border: 1px solid black;}
input {width: 100%;}
</style>
<script src="cordova-2.5.0.js"></script>
<script type="text/javascript" charset="utf-8">
var deviceReady = false;
/**
* Take picture with camera
*/
function takePicture() {
navigator.camera.getPicture(
function(uri) {
var img = document.getElementById('camera_image');
img.style.visibility = "visible";
img.style.display = "block";
img.src = uri;
document.getElementById('camera_status').innerHTML = "Success";
},
function(e) {
console.log("Error getting picture: " + e);
document.getElementById('camera_status').innerHTML = "Error getting picture.";
},
{ quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI});
};
/**
* Select picture from library
*/
function selectPicture() {
navigator.camera.getPicture(
function(uri) {
var img = document.getElementById('camera_image');
img.style.visibility = "visible";
img.style.display = "block";
img.src = uri;
document.getElementById('camera_status').innerHTML = "Success";
},
function(e) {
console.log("Error getting picture: " + e);
document.getElementById('camera_status').innerHTML = "Error getting picture.";
},
{ quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY});
};
/**
* Upload current picture
*/
function uploadPicture() {
// Get URI of picture to upload
var img = document.getElementById('camera_image');
var imageURI = img.src;
if (!imageURI || (img.style.display == "none")) {
document.getElementById('camera_status').innerHTML = "Take picture or select picture from library first.";
return;
}
// Verify server has been entered
server = document.getElementById('serverUrl').value;
if (server) {
// Specify transfer options
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
options.chunkedMode = false;
options.headers = {
Connection: "close"
}
options.chunkedMode = false;
// Transfer picture to server
var ft = new FileTransfer();
ft.upload(imageURI, 'http://mywebsite/upload.php', function(r) {
document.getElementById('camera_status').innerHTML = "Upload successful: "+r.bytesSent+" bytes uploaded.";
}, function(error) {
document.getElementById('camera_status').innerHTML = "Upload failed: Code = "+error.code;
}, options);
}
}
/**
* View pictures uploaded to the server
*/
function viewUploadedPictures() {
// Get server URL
server = document.getElementById('serverUrl').value;
if (server) {
// Get HTML that lists all pictures on server using XHR
var xmlhttp = new XMLHttpRequest();
// Callback function when XMLHttpRequest is ready
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState === 4){
// HTML is returned, which has pictures to display
if (xmlhttp.status === 200) {
document.getElementById('server_images').innerHTML = xmlhttp.responseText;
}
// If error
else {
document.getElementById('server_images').innerHTML = "Error retrieving pictures from server.";
}
}
};
xmlhttp.open("GET", server , true);
xmlhttp.send();
}
}
/**
* Function called when page has finished loading.
*/
function init() {
document.addEventListener("deviceready", function() {deviceReady = true;}, false);
window.setTimeout(function() {
if (!deviceReady) {
alert("Error: PhoneGap did not initialize. Demo will not run correctly.");
}
},2000);
}
</script>
</head>
<body onload="init();">
<h3>PhoneGap Camera Upload Demo</h3>
<div>
<h3>Server URL for upload.php:</h3>
<input id="serverUrl" type="text" value="http://mywebsite/pictures.php" />
</div>
<br/>
<!-- Camera -->
<div>
<h3>Camera:</h3>
<b>Status:</b> <span id="camera_status"></span><br>
<b>Image:</b> <img style="width:120px;visibility:hidden;display:none;" id="camera_image" src="" />
</div>
<!-- Actions -->
<div>
<input type="button" onclick="takePicture();" value="Take Picture" /><br/>
<input type="button" onclick="selectPicture();" value="Select Picture from Library" /><br/>
<input type="button" onclick="uploadPicture();" value="Upload Picture" />
</div>
<br/>
<!-- Server pictures -->
<div>
<h3>Server:</h3>
<b>Images on server:</b>
<div id="server_images"></div>
</div>
<!-- Actions -->
<div>
<input type="button" onclick="viewUploadedPictures();" value="View Uploaded Pictures" />
</div>
</body>
</html>
Make sure your upload function is similar like this
function upload() {
var img = document.getElementById('image');
var imageURI = img.src;
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = imageURI.substr(imageURI.lastIndexOf('/') + 1);
options.mimeType = "image/jpeg";
var params = new Object();
options.params = params;
options.chunkedMode = false;
var ft = new FileTransfer();
ft.upload(imageURI, "https://www.example.com/upload.php", win, fail,
options);
}
It's working 100%.
Reference: http://blog.revivalx.com/2014/07/12/upload-image-using-file-transfer-cordova-plugin-for-ios-and-android/