Upload Image using ajax (json) - php

I need to upload image using ajax. Elaborating my point:
I need to pass my image data to a PHP page and check the type, size, name and all other attributes of the file. If all attributes matches, then only I need to transfer the file. Problem here is passing of data should be done in JSON(AJAX) format only. One more important thing is that I don't have to convert it to base64.
If you can help me in this, You are most welcome.
Thanks in advance.

The idea in SO is to work on the OP current code. I mean, we are not here to make all the job, because it should have a price. Anyway, here is a workaround for your issue:
Convert your image to base64 using javascript. This useful method works like a charm:
// Code taken from MatthewCrumley (http://stackoverflow.com/a/934925/298479)
function getBase64Image(img) {
// Create an empty canvas element
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// Copy the image contents to the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Get the data-URL formatted image
// Firefox supports PNG and JPEG. You could check img.src to guess the
// original format, but be aware the using "image/jpg" will re-encode the image.
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
Then just pass the returned string as base64 through ajax:
$.ajax({
url: 'path/to/your/script.php',
type: 'post',
data: { paramName: imagedata } // the returned data from above js method,
/*...*/
});
And, in PHP side, just return the string to an image file:
// Code taken from Austin Brunkhorst (http://stackoverflow.com/a/15153931/3648578)
function base64_to_jpeg($base64_string, $output_file) {
$ifp = fopen($output_file, "wb");
$data = explode(',', $base64_string);
fwrite($ifp, base64_decode($data[1]));
fclose($ifp);
return $output_file;
}

Related

Laravel, FineUploader and FileReader API: compare hash of file before uploading

I'd like to compare the hashed version of the file against the data stored in the database, so I can abort duplicate uploads.
Being quite "new" to the subjects of hashing and the FileReader API, I'm finding the process a bit confusing.
I am using the frontend library SparkMD5.js
Test n1 compare two strings:
// frontend
$.post(url, {sparkMD5('random text')})
// backend
$input->hash == md5('random text') // outputs true
Test n2 - inside fineuploader onSubmit event handler
// frontend
var file = this.getFile(id);
var reader = new FileReader();
//
reader.onload = function(e) {
var data = reader.result;
var hexHash = SparkMD5.hash(data);
console.log(hexHash);
}
var res = reader.readAsDataURL(file); // or reader.readAsBinaryString(file)
......
//backend
$file = Input::file('qqfile');
$hash = md5(file ) // or md5_file(file )
$hash == $input->hexHash // outputs false
My questions:
1) Why is the result of md5($file) == md5_file($file) \\ false ?
2) What's the correct way of reading a file readAsDataURL or readAsBinaryString ?
3) Is there a way to read and hash the result of fineuploader's getFile(id) which returns File or Blob, without using filereader api?
Answers to the above questions may be considered broad and out of scope of my immediate problem, but i'd like to understand the subject as best as possible.
Thanks.
Input::file() returns an instance of Illuminate\Http\UplaodedFile, so to get the hash of its contents you can do the following:
// md5_file takes in the file path as argument
$hash = md5_file(Input::file('yourfile')->path());
readAsDataURL() is much safer because the file is encoded as base64. Just make sure that the server is aware of the encoding, meaning remove the first characters up to the comma then decode the rest as base64. More information here: fileReader.readAsBinaryString to upload files
According to this you still have to use filereader: How to include Content-MD5 header in FineUploader Azure request?.
Thanks to #alio f I was able to come up with a solution. Here's the code.
frontend
var t = this;
var reader = new FileReader();
var file = this.getFile(id);
reader.addEventListener("load", function () {
var base64result = reader.result.split(',')[1]; // only get base64 string
var hash = SparkMD5.hash(base64result);
}, false);
var data = reader.readAsDataURL(file);
Refer to FineUploader docs for the onSubmit handler.
backend
$this->file = Input::file('qqfile');
$base64 = base64_encode(file_get_contents($this->file));
$hash = md5($base64);
Comparing frontend's md5 and backend's md5 now returns true

Can i get blob pdf content from encoded url in php

I have a BLOB URL that has the pdf file with the content:
blob:http://localhost/468479b7-7db1-4e35-ab35-acf9ff0739f8
Using the filereader i convert it to base64:
var myReader = new FileReader();
var blob = new Blob([v.src], {type: "application/pdf"});
myReader.readAsDataURL(blob);
myReader.onload = function(event) {
result = event.target.result;
console.log(result);
console.log(v.src);
};
The result is:
data:application/pdf;base64,YmxvYjpodHRwOi8vbG9jYWxob3N0LzQ2ODQ3OWI3LTdkYjEtNGUzNS1hYjM1LWFjZjlmZjA3MzlmOA==
Now can i get the pdf content from the encoded url?
If not, what are my options?
Extract the content part. Decode and save into a file.
$data = explode(';',"data:application/pdf;base64,YmxvYjpodHRwOi8vbG9jYWxob3N0LzQ2ODQ3OWI3LTdkYjEtNGUzNS1hYjM1LWFjZjlmZjA3MzlmOA");
$encoded = explode(',',$data[1]);
file_put_contents("test.pdf",base64_decode($encoded[1]));

Can't upload images to the server on mobile

I am looking for any pointers what I am doing wrong here?
Situation:
I created a simple form on my website that requires the user to enter some text data and an image. This information is then stored on the server - picture separately, and the text data in a json file.
I have tested it with multiple image formats on my desktop (I allow only the most common types, such as jpg, png, or bmp). All seems to be fine. However, it isn't so smooth on mobile (iOS). When I attempt to upload a screenshot (shows as a png format), or a picture I just took (jpg), the response that comes back says Missing picture, which means that no data was received on the server. The thing is that this is not always the case, some screenshots come through, some don't.
I am encoding the picture as a base64 string on the client. I tried logging it to make sure it goes through, and it seems to be fine. However, when I log the received parameters on the server, in these failed cases, the picture string is really empty! All I do is I read the $_REQUEST or $_POST parameters (it's in PHP).
This error has been replicated only on mobile so far. On the front side, I guess this is the most relevant piece of code, but if you need more let me know! You can also inspect that website I included, but it will be slightly more difficult as it's minified.
function init_form_submit () {
var button = document.getElementById('form-submit-btn'),
image_upload_button = document.getElementById('picture');
if (!button || !image_upload_button) return;
image_upload_button.addEventListener('change', function (event) {
preview_image(this);
});
button.addEventListener('click', function (event) {
// Hijack the form submit.
event.preventDefault();
show_form_loader();
var form_validator = FormValidator(GLOB.form_node);
if (!form_validator.valid) {
form_submitted_callback();
}
else {
var http = new XMLHttpRequest();
var formData = new FormData();
formData.append("about", form_validator.fd.about);
formData.append("email", form_validator.fd.email || '');
formData.append("handle", form_validator.fd.handle);
formData.append("name", form_validator.fd.name);
formData.append("picture", GLOB.picture);
http.open('POST', 'https://lmen.us/royalkitten/api/apply-royal-kitten/index.php', true);
http.setRequestHeader('Content-type', 'multipart/form-data');
http.onreadystatechange = function () {
var response;
if (http.readyState !== 4 || http.status !== 200) return;
try {
response = JSON.parse(http.responseText);
}
catch (error) {
response = http.responseText;
console.log(response);
}
form_submitted_callback(response);
}
http.send(formData);
}
});
}
Here is how I store the image data in the GLOB.picture variable. This function is called only twice - once in the code above when the user chooses an image, and once in a callback after a successful submission as a way to reset the form to its original state.
function preview_image (input) {
var preview_label = document.getElementById('picture-label'),
preview_element = document.getElementById('picture-preview');
if (!input.files.length) {
if (preview_label) {
preview_label.innerHTML = 'Select a file';
}
if (preview_element) {
preview_element.src = './images/image-placeholder-600x600.jpg';
}
GLOB.picture = null;
return;
}
var reader = new FileReader(),
file = input.files[0];
if (!file) return;
reader.onload = function (event) {
var image_data = event.target.result;
if (preview_label) {
preview_label.innerHTML = file.name;
}
if (preview_element) {
preview_element.src = image_data;
}
GLOB.picture = image_data;
}
reader.readAsDataURL(file);
}
I guess, the problem is that your image is probably bigger than PHP max size allowed for a POST request. You should send your form as multipart/form-data, and send your image as a file. On the server side, you should get it via $_FILE instead of $_POST...
To send your image as a file, there are multiple solutions. First, you could send a base-64 encoded Blob, but it would be 30% larger than the original file (because of base-64 encoding).
What I would recommend to you is that you send the file in its original binary format, which is easier to implement and faster to upload.
To do so, you just need to send as-is the content of input.files[0]. let's say you set a GLOB.pictureFile=input.files[0] in your preview_image() function. you then just send it in the form like this :
formData.append("picture", GLOB.pictureFile);

Phonegap 3.7.0 e-mail file from input[type=file]

I'm having a problem with sending a file from an app I'm developing with phonegap.
I'm new to phonegap, so I might be trying to solve this in an entirely wrong way, so let me describe the the end goal first.
I'm developing a car rental app, I need to make a contact form, so users can leave an order to rent a car.
The form requires user to put in some basic information, like name and phone number, and also attach a photo or a scan of driver's license.
I was able to figure out the basic info part. I'm using $.ajax dataType: 'jsonp', to send the data to the server and then simply e-mail it to my client's address.
But I can find a way to send the file to the server.
I'm using an input[type=file] field to let the user choose what file to upload.
I've tried uploading file using FileTransfer, but apparently input[type=file] gives you some fake file path, that can't be directly used by FileTransfer.upload()
Problem is, I can't understand how can I get a proper file path for FileTransfer.upload function.
I've tried doing it another way, by reading the file using FileReader.
I tried reading the file and setting an image src to the result, but it doesn't work (it show broken image icon instead of an image, the same code works on PC).
I also tried to output it as text, that does output some data (so why doesn't it work for image src?).
Because I did manage to output the data read from the file as text I thought I will send that to the server and save it.
So here is how the code would look like:
On input change I read the file into a global variable
$(".file1").change(function(e){
var caster = e.target;
var files = caster.files;
if(FileReader && files && files.length) {
var fr = new FileReader();
fr.onloadend = function(e) {
//$(".image").attr("src",e.target.result);
window.file1base64 = e.target.result;
}
fr.readAsDataURL(files[0]);
}
});
Then, when user presses a button, I run FileTransfer.upload and then check every 0.1 seconds, whether the file upload is complete
function uploadSuccess(r) {
$(".output").append(" Success ");
window.fileStatus = true;
}
function uploadError(error) {
$(".output").append(" Error "+error.code+" ");
window.fileStatus = true;
window.fileError = error.code;
}
function uploadFile() {
$(".output").append(" uploadFile ");
file = $('.file1').val().split('\\').pop();
$(".output").append(" File-"+file+" ");
if(file){
$(".output").append(" fileExists ");
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = file;
options.mimeType = "image/jpeg";
options.chunkedMode = false;
options.headers = {
Connection: "close"
};
$(".output").append(" FileUploadOptions ");
window.fileStatus = false;
window.fileError = '';
//fileuri = $(".image").attr("src");
fileuri = window.file1base64;
$(".output").append(" fileuri ");
var ft = new FileTransfer();
ft.upload(fileuri, encodeURI("http://***.***/savefile.php"), uploadSuccess, uploadError, options);
$(".output").append(" upload ");
checkFile();
}
}
function checkFile() {
if(!window.fileStatus) {
$(".output").append(" check ");
setTimeout(checkFile, 100);
return;
}
}
After some checks, it prints out Error 3 and I can't figure out what that means or how to fix it.
Server side code is simply this:
Get the file and save it
$dir_name = dirname(__FILE__)."/uploadedimages/";
move_uploaded_file($_FILES["file"]["tmp_name"], $dir_name."test.txt");
But no file is created on the server.
use the FormData object to get the form data (including input file) and submit it this way:
var data = new FormData($('#yourFormID')[0]);
$.ajax({
url: serverURL,
data: data,
cache:false,
contentType: false,
processData: false,
type: 'POST',
error: function(jqXHR,textStatus,errorThrown){
},
success: function(data){
}
});
You should set the FILEURL in some variable and image in some html image element and then use it to transfer the image.
like this:
function onPgCameraSuccess(imageData) {
fileEntry.file(
function(fileObj) {
var previewImage= document.getElementById('SomeImageElement');
fileName=imageData.substr(imageData.lastIndexOf('/')+1);
fileURL=imageData;
previewImage.src =imageData;
$('#SomeTextBox').val(fileName);
});
}
function SubmitPhoto(){
var uOptions = new FileUploadOptions();
var ft = new FileTransfer();
uOptions .fileKey = "keyofyourfileonserver";
uOptions .fileName = fileName;
uOptions .mimeType = "image/jpeg";
uOptions .httpMethod = "POST";
uOptions .params = params;
ft.upload(fileURL,
urlofsvc,
photoSuccess,
photoFail,
uOptions,
true
);}

Saving HTML5 canvas data to server

I know there is a lot of questions regarding this but currently I am trying to save user created HTML5 canvas data to a specific folder on my web server.
I am already able to save an image to server using the following:
function sendData(postData){
var ajax = new XMLHttpRequest();
ajax.open("POST",'saveFrame.php',true);
ajax.setRequestHeader('Content-Type', 'canvas/upload');
var comicID = document.getElementById('comicID').value;
ajax.onreadystatechange=function()
{
if (ajax.readyState == 4)
{
alert("Frame saved");
}
}
ajax.send(postData);
}
saveFrame.PHP File
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
// Get the data like you would with traditional post
$rawImage=$GLOBALS['HTTP_RAW_POST_DATA'];
// Remove the headers
$removeHeaders=substr($rawImage, strpos($rawImage, ",")+1);
// decode it from base 64 and into image data only
$decode=base64_decode($removeHeaders);
// save to your server
$saveName = "test.jpeg";
$fopen = fopen($saveName, 'wb' );
fwrite( $fopen, $decode);
fclose( $fopen );
}
?>
What I want to be able to do is pass some more variables along side the image so that I can dynamically look up my database using PHP within the saveFrame.php file to determine what filename it should be saved as. I'm unsure how to accomplish this as I'm not accustomed to using AJAX.
Any advice is appreciated,
Alex
You can use the html5 canvaspixelarray property to obtain the canvas data.

Categories