How can I upload a image immediately after user pick a file from browser?
Like in Facebook, when you need to upload your cover or profile image, you need to
select file and after that upload starts.
I have for now just my input tag
<input id="chaf" type="file"/>
and js that can run the function after file is picked
$('#chaf').change(function(){
// Upload image start
});
But how can I send the data to php in this way?
You can upload files as a Base64 string using Ajax (without being refreshed).
some thing like this.
$(document).on("change", ".custom-file-input", this, function(e){
GetBase64( e.target );
});
function GetBase64( input ) {
if ( input.files && input.files[0] ) {
var FR= new FileReader();
FR.onload = function(e) {
var str = e.target.result;
/* preview it ( if you wanted to ) */
$('#preview-img').attr( "src", str );
/* upload it to server */
UploadFile( str );
};
FR.readAsDataURL( input.files[0] );
}
}
function UploadFile( file_str ) {
console.log( file_str );
/* use $.ajax to upload your file */
}
refer this answer for storing base64 in disk base64 string to an image file
in php some thing like this
<?php
$base64Str = $_REQUEST[ "your-post-variable" ];
$img = explode(',', $base64Str);
$fp = fopen( "my-image.png" , "wb");
fwrite($fp, base64_decode( $img[1]) );
fclose($fp);
?>
You should check out: https://github.com/Widen/fine-uploader.
This does exactly what you want. It will start uploading the second they select the image.
It allso supports drag& drop and multiple file upload.
Another option - using IaaS for file uploading, such as Uploadcare (this system is maintained by us):
https://uploadcare.com
All you have to do is add the JS library into your header:
<script>
UPLOADCARE_PUBLIC_KEY = 'PUBLIC-KEY';
UPLOADCARE_AUTOSTORE = true;
</script>
<script charset="utf-8" src="https://ucarecdn.com/widget/1.4.6/uploadcare/uploadcare-1.4.6.min.js"></script>
and replace file input with specially marked hidden input in your form:
<input type="hidden" role="uploadcare-uploader" name="file_fieldname" />
It will add a widget to the page. Once the file is selected (from local drive, URL, Dropbox/Box/GoogleDrive/Facebook/Instagram/etc.) or dropped onto the widget, upload will start immediately.
The form will send an UUID of the uploaded file to your server, so you can store a reference to it.
Related
I am trying to upload an image created from Java's toDataURL, submitted in a form automatically with javascript, captured by PHP and converted using imagecreatefrompng() and assigned to a variable.
Here is the code to start with:
Javascript code:
if(getImageData == true){
console.log("Saving avatar as image...");
window.setTimeout(function () {
imgData = renderer.domElement.toDataURL("image/png");
document.getElementById('avatarimg').src = imgData;
document.getElementById("timg").value = imgData;
console.log(imgData);
document.getElementById("form1").submit();
console.log("Avatar saved as PNG img.");
}, 300);
getImageData = false;
PHP code:
if($_POST['timg']){
$renderedav = imagecreatefrompng($_POST['timg']);
imageAlphaBlending($renderedav, true);
imageSaveAlpha($renderedav, true);
$target = "images/Avatars/";
$newname = md5($_POST['timg']);
echo ("<font color='#000000'>Image rendered. - " . $newname . " </font>");
$target = $target . $newname . ".png";
if(move_uploaded_file($renderedav, $target))
{ echo("File uploaded."); }else{echo("Error uploading file.");}
}
When I display the image as a raw img using the imgData, everything looks great, but I want to create an actual image from that data and upload it to a directory on my database using the name created in $newname. Is this possible to do? Am I going about it correctly? I know move_uploaded_file() is intended to move a suspended file from a file form element to a new location, but in my research I couldn't find another method that does this.
There are a couple things here that are not going to work:
You can not write text over top by echoing some html, you have to use a gdlib text function like imagettftext(). One note, you have to point to a font file to use it (Resource here). If you are not trying to write this echo ("<font color='#000000'>Image rendered. - " . $newname . " </font>"); over top of the image, disregard this part of the script HOWEVER, you still can not do it because if you echo anything (or have empty space before your script), it will corrupt the image.
You have to use imagepng() (Resource here) to save the file.
PHP Script:
if($_POST['timg']){
// Set file path info
$target = "images/Avatars/";
$newname = md5($_POST['timg']);
$target = $target.$newname.".png";
// Start gdlib functions
$renderedav = imagecreatefrompng($_POST['timg']);
imagealphablending($renderedav, true);
imagesavealpha($renderedav, true);
$fColor_white = imagecolorallocate($renderedav, 255, 255, 255);
// Path to truetype font
$font = 'font.TTF';
// Add text to image
imagettftext($renderedav, 25, 0, 75, 300, $fColor_white, $font, "Image rendered. - ".$newname);
// Here you output the png and use the second parameter to save to a destination
imagepng($renderedav,$target);
// Now you destroy the resouce
imagedestroy($renderedav);
}
I have written a php script for uploading images. I want to use this script in my all pages. The problem is that the name of input file <input type="file" name="input_name"> in the server side. I am using a different input name so I do not know how I detect the input name in the server side?
Html code :
<input type="file" name="my_input_name" id="inptId">
JS Code:
var fd = new FormData();
var image = document.getElementById("inptId");
fd.append("my_input_name",image);
$.ajax({
method:post,
url:uniq_file_uploader.php,
....,
....,
data:fd,
sucess:function(e){....}
});
EG: my php code:
<?php
if($_SERVER["REQUEST_METHOD"] === "post"){
if(!empty($_FILES['Constant_Name']['name'][0])){//check also for multiple uploads
// constant_name is name of input file (eg. my_input_name)
// but problem is input name is not always same..
// on every page it is different name
}else {return "NO file selected";}
if(!empty($_FILES['Constant_Name']['name'])){
//it is for one file upload detect
//this is for one file upload beacuse this is for using upload his avatar. can't be a lot of avatar
}else{return "no file selected";}
}else {return "request is not post"}
?>
<?php
if($_SERVER["REQUEST_METHOD"] === "post"){
if(!empty($_FILES)) {
$cname = key($_FILES); //get the first key from $_FILES
} else {
$cname = '';
}
if(!empty($_FILES[$cname]['name'][0])){//check also for multiple uploads
// constant_name is name of input file (eg. my_input_name)
// but problem is input name is not always same..
// on every page it is different name
}else {return "NO file selected";}
if(!empty($_FILES[$cname]['name'])){
//it is for one file upload detect
}else{return "no file selected";}
}else {return "request is not post"}
?>
You can access it with $_FILES['my_input_name'] just like $_GET and $_POST.
I am trying to save the picture to temporary folder first once the user selected it from the file options. And then save it to move folder after submitting the form.
Here is the code for uploading:
$id = $this->Session->read('Auth.User.id');
$userData = $this->User->findById($id);
if ($userData['User']['id'] === $this->Session->read('Auth.User.id')) {
$this->set('userData', $userData);
} else {
throw new NotFoundException(__('You are not allowed to this page!'));
}
move_uploaded_file($fileTmp, WWW_ROOT.'files\Users'.DS.$uid.DS.$fileInfo['tmpFileName']);
This code allow me to save it directly to the folder without saving it to temp folder.
I want to save what is being previewed.
Here is my javascript in previewing:
//preview
$("#file").change(function() {
var file = this.files[0];
var imagefile = file.type;
var imagesize = file.size;
var match= ["image/jpeg","image/png","image/jpg","image/gif"];
$('.upload-submit').prop('disabled',false).css('opacity',1);
if(!((imagefile==match[0]) || (imagefile==match[1]) || (imagefile==match[2]) || (imagefile==match[3])))
{
$("#message").html("<p id='error' style='color:red;'>Please Select A valid Image File</p>"+"<h4 style='color:red;'>Note</h4>"+"<span id='error_message' style='color:red;'>Only jpeg, jpg, gif and png Images type allowed</span>");
return false;
} else if (imagesize > 6000000){
$("#message").html("<p id='error' style='color:red;'>Your file size is higher than the allowed size (6MB)</p>");
return false;
}
else
{
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[0]);
var imgData = reader.onload; }
});
function imageIsLoaded(e) {
$("#file").css("color","green");
$('#image_preview').css("display", "block");
$('#previewing').attr('src', e.target.result);
$('#previewing').attr('width', '250px');
$('#previewing').attr('height', '230px');
};
and my HTML:
<form method="post" action="/users/profileimg_edit" enctype="multipart/form-data" id="uploadimage">
<?php echo $this->Session->flash(); ?>
<input type="file" name="file" id="file" class="upload-image-btn" >
<div id="image_preview"><img id="previewing" src="/images/noimage.png" width="80" height="80" />
<div id="message"></div>
</div>
<button class="upload-submit"> Upload Image </button>
</form>
With this code the user can view what did he/she selected and save it, but I want is to save it first in a temporary folder.
Thank you for help that will be given.
First move the picture to a temporary directory on the the server (say, WWW_ROOT . 'tmp' . DS . $fileInfo['tmpFileName']), then use that path in your preview (so the URL becomes someting like http://my.server.com/tmp/b5c8f033dfaa.jpg). Then, when the user is done previewing, move the file to the final destination.
However, you must keep track of the temporary filename ($fileInfo['tmpFileName']) because that info is lost if you go to the next page. You can put it in the URL or store it in the Session object.
You might also want to add cronjob to remove old uploaded files from the tmp directory, because there will usually be some abandonded file uploads, etc.
I followed this tutorial on my vps: http://permadi.com/2010/10/html5-saving-canvas-image-data-using-php-and-ajax/
testSave.php
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
// Get the data
$imageData=$GLOBALS['HTTP_RAW_POST_DATA'];
// Remove the headers (data:,) part.
// A real application should use them according to needs such as to check image type
$filteredData=substr($imageData, strpos($imageData, ",")+1);
// Need to decode before saving since the data we received is already base64 encoded
$unencodedData=base64_decode($filteredData);
//echo "unencodedData".$unencodedData;
$randnum = rand(1111111111,9999999999);
// Save file. This example uses a hard coded filename for testing,
// but a real application can specify filename in POST variable
$tmpfname = tempnam("http://123.xx.xx.xx/test/tmp/", "FOO");
$fp = fopen(http://123.xx.xx.xx/test/test . uniqid() .".png","wb");
fwrite( $fp, $unencodedData);
fclose( $fp );
}
?>
JS
function saveViaAJAX()
{
var testCanvas = document.getElementById("testCanvas");
var canvasData = testCanvas.toDataURL("image/png");
var postData = "canvasData="+canvasData;
var debugConsole= document.getElementById("debugConsole");
debugConsole.value=canvasData;
//alert("canvasData ="+canvasData );
var ajax = new XMLHttpRequest();
ajax.open("POST",'testSave.php',true);
ajax.setRequestHeader('Content-Type', 'canvas/upload');
//ajax.setRequestHeader('Content-TypeLength', postData.length);
ajax.onreadystatechange=function()
{
if (ajax.readyState == 4)
{
//alert(ajax.responseText);
// Write out the filename.
document.getElementById("debugFilenameConsole").innerHTML="Saved as<br><a target='_blank' href='"+ajax.responseText+"'>"+ajax.responseText+"</a><br>Reload this page to generate new image or click the filename to open the image file.";
}
}
ajax.send(postData);
}
The problem is that when the user clicks 'send via ajax', there is no image sent/generated in the server directory(http://prntscr.com/8bhmxa). This is the outcome: http://prntscr.com/8bhi62 and everything in the directory remains unchanged.
What should happen is for a link of the image to be generated under the 'Saved as'
Any solutions?
P.S.
Is there anyway to echo the image link with php?
The problem is with your AJAX. Refer Url here the code is given for saving canvas with php and ajax.
Link
I'm trying to upload generated client side documents (images for the moment) with Dropzone.js.
// .../init.js
var myDropzone = new Dropzone("form.dropzone", {
autoProcessQueue: true
});
Once the client have finished his job, he just have to click a save button which call the save function :
// .../save.js
function save(myDocument) {
var file = {
name: 'Test',
src: myDocument,
};
console.log(myDocument);
myDropzone.addFile(file);
}
The console.log() correctly return me the content of my document
data:image/png;base64,iVBORw0KGgoAAAANS...
At this point, we can see the progress bar uploading the document in the drop zone but the upload failed.
Here is my (standart dropzone) HTML form :
<form action="/upload" enctype="multipart/form-data" method="post" class="dropzone">
<div class="dz-default dz-message"><span>Drop files here to upload</span></div>
<div class="fallback">
<input name="file" type="file" />
</div>
</form>
I got a Symfony2 controller who receive the post request.
// Get request
$request = $this->get('request');
// Get files
$files = $request->files;
// Upload
$do = $service->upload($files);
Uploading from the dropzone (by drag and drop or click) is working and the uploads are successfull but using the myDropzone.addFile() function return me an empty object in my controller :
var_dump($files);
return
object(Symfony\Component\HttpFoundation\FileBag)#11 (1) {
["parameters":protected]=>
array(0) {
}
}
I think i don't setup correctly my var file in the save function.
I tryied to create JS image (var img = new Image() ...) but without any success.
Thanks for your help !
Finally i found a working solution without creating canvas :
function dataURItoBlob(dataURI) {
'use strict'
var byteString,
mimestring
if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
byteString = atob(dataURI.split(',')[1])
} else {
byteString = decodeURI(dataURI.split(',')[1])
}
mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]
var content = new Array();
for (var i = 0; i < byteString.length; i++) {
content[i] = byteString.charCodeAt(i)
}
return new Blob([new Uint8Array(content)], {type: mimestring});
}
And the save function :
function save(dataURI) {
var blob = dataURItoBlob(dataURI);
myDropzone.addFile(blob);
}
The file appears correctly in dropzone and is successfully uploaded.
I still have to work on the filename (my document is named "blob").
The dataURItoBlob function have been found here : Convert Data URI to File then append to FormData
[EDIT] : I finally wrote the function in dropzone to do this job. You can check it here : https://github.com/CasperArGh/dropzone
And you can use it like this :
var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmAAAAKwCAYAAA...';
myDropzone.addBlob(dataURI, 'test.png');
I can't comment currently and wanted to send this to you.
I know you found your answer, but I had some trouble using your Git code and reshaped it a little for my needs, but I am about 100% positive this will work for EVERY possible need to add a file or a blob or anything and be able to apply a name to it.
Dropzone.prototype.addFileName = function(file, name) {
file.name = name;
file.upload = {
progress: 0,
total: file.size,
bytesSent: 0
};
this.files.push(file);
file.status = Dropzone.ADDED;
this.emit("addedfile", file);
this._enqueueThumbnail(file);
return this.accept(file, (function(_this) {
return function(error) {
if (error) {
file.accepted = false;
_this._errorProcessing([file], error);
} else {
file.accepted = true;
if (_this.options.autoQueue) {
_this.enqueueFile(file);
}
}
return _this._updateMaxFilesReachedClass();
};
})(this));
};
If this is added to dropzone.js (I did just below the line with Dropzone.prototype.addFile = function(file) { potentially line 1110.
Works like a charm and used just the same as any other. myDropzone.addFileName(file,name)!
Hopefully someone finds this useful and doesn't need to recreate it!
1) You say that: "Once the client have finished his job, he just have to click a save button which call the save function:"
This implies that you set autoProcessQueue: false and intercept the button click, to execute the saveFile() function.
$("#submitButton").click(function(e) {
// let the event not bubble up
e.preventDefault();
e.stopPropagation();
// process the uploads
myDropzone.processQueue();
});
2) check form action
Check that your form action="/upload" is routed correctly to your SF controller & action.
3) Example Code
You may find a full example over at the official Wiki
4) Ok, thanks to your comments, i understood the question better:
"How can i save my base64 image resource with dropzone?"
You need to embedd the image content as value
// base64 data
var dataURL = canvas.toDataURL();
// insert the data into the form
document.getElementById('image').value = canvas.toDataURL('image/png');
//or jQ: $('#img').val(canvas.toDataURL("image/png"));
// trigger submit of the form
document.forms["form1"].submit();
You might run into trouble doing this and might need to set the "origin-clean" flag to "true". see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#security-with-canvas-elements
how to save html5 canvas to server