Upload a file with AngularJS and PHP - javascript

I want to upload a file while using AngularJS for frontend and PHP for backend.
When I would leave Angular aside, my HTML form would look like this:
<form enctype="multipart/form-data" action="process.php" method="POST" >
File: <input name="userfile" type="file"/>
<input type="submit" value="Send File" />
</form>
My PHP in process.php is this:
$tmpFilePath = $_FILES['userfile']['tmp_name'];
if ($tmpFilePath != ""){
$newFilePath = "my-uploads/" . $_FILES['userfile']['name'];
move_uploaded_file($tmpFilePath, $newFilePath);
}
So far, everything works fine, file is uploaded by clicking submit.
But I need the whole thing to be done with Angular. So I changed my HTML to this:
<form ng-submit="processForm()" >
File: <input name="userfile" type="file" ng-model="formData.file"/>
<input type="submit" value="Send File" />
</form>
The code inside my Angular-controller looks like this:
$scope.formData = '';
$scope.processForm = function() {
$http({
method : 'POST',
url : 'process.php',
data : $.param($scope.formData),
headers : { 'Content-Type': undefined }
})
.success(function(data) {
console.log(data);
console.log('success!');
})
.error(function(data) {
console.log(data)
});
};
When I click "submit", the console tells me "success!", but no file is uploaded. I think the problem is "data" and "headers" in th $http-request? But I'm really unsure about this and couldn't find a solution on the net so far. Does anybody know what I have to do to get my file uploaded while using angulars $http-functionality?

Angular can't upload files using AJAX without using the HTML5 file API.
Either change your code to use the file API and submit the binary content or use an external library such as angular-file-upload.

<input type='file' name="Filename" data-ng-file-select onchange="scope.setFile(this)" id="imgInp"> (html)
window.scope = $scope;
$scope.setFile = function (ele) {
var photofile = ele.files[0];
var reader = new FileReader();
console.log(photofile);
reader.onload = function (e) {
$scope.$apply(function () {
console.log(e);
$scope.prev_img = e.target.result;
$scope.prev_img = angular.copy($scope.prev_img);
$http({
method: 'POST',
url: 'api/1.php',
data: { 'imagepath': $scope.prev_img },
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }
})
.success(function (data) {
console.log(data);
})
.error(function (error) {
$scope.data.error = error;
});
});
}; (angurlarjs)
<?php
include 'db_connect.php';
include 'functions.php';
//$levels = array();
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
$idUser = $request->imagepath;
echo $idUser;
// CLOSE CONNECTION
mysqli_close($mysqli);
echo json_encode($json);
?>(php)

Related

Product upload with Dropzone and Laravel

I want to upload a product with multiple images using Dropzone, I have a form which has other fields like price, name etc. I have seen other tutorials but they only upload images not images with other fields(price, name) at once. I have set the Dropzone which shows the preview but if I submit the button I get a validation Please enter product image. How can I pass images to the controller using Dropzone?
Controller
public function store(Request $request)
{
$formInput=$request->except('filename');
$product = product::create(array_merge($formInput, [
'user_id' => Auth::user()->id
]));
foreach ($request->file as $photo) {
$filename = $photo->store('public/photos');
ProductsPhoto::create([
'product_id' => $product->id,
'filename' => $filename
]);
}
}
Blade
//The form
<div class="panel-body">
<form>
#csrf
<input type="hidden" value="{{csrf_token()}}" id="token"/>
<label for="pro_name">Name</label>
<input type="text" class="form-control" name="pro_name" id="pro_name" placeholder="Enter product name">
<label for="pro_price">Price</label>
<input type="text" class="form-control" name="pro_price" id="pro_price" placeholder="Enter price">
<label for="photos">Choose 5 Images</label>
<div class="needsclick dropzone" id="document-dropzone"> // Display images preview
</div>
<input type="submit" class="btn btn-primary" value="Submit" id="btn"/>
</div>
Ajax
//This is how I submit the form
<script>
var token = $("#token").val();
$(document).ready(function(){
$("#btn").click(function (e) {
e.preventDefault();
$("#loading").show();
var url = '{{ route('product.store') }}';
var form = $('form')[0]; // You need to use standard javascript object here
var formData = new FormData(form);
formData.append('_token', token); // adding token
$.ajax({
url: url,
data: formData, //just that without variables
type: 'POST',
cache: false,
contentType: false, // NEEDED, DON'T OMIT THIS (requires jQuery 1.6+)
processData: false, // NEEDED, DON'T OMIT THIS
success:function(data){
if($.isEmptyObject(data.error)){
$("#msg").html("Product has been added successfull");
$("#msg").fadeOut(3000);
window.location.href = "<?php echo url('seller/product') ?>";
$("#loading").hide();
}
else{
printErrorMsg(data.error);
}
}
});
function printErrorMsg (msg) {
$("#loading").hide();
$(".print-error-msg").find("ul").html('');
$(".print-error-msg").css('display','block');
$.each( msg, function( key, value ) {
$(".print-error-msg").find("ul").append('<li>'+value+'</li>');
});
}
});
});
var uploadedDocumentMap = {}
Dropzone.options.documentDropzone = {
url: '{{ route('product.store') }}',
maxFilesize: 10, // MB
addRemoveLinks: true,
headers: {
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
success: function (file, response) {
$('form').append('<input type="hidden" name="document[]" value="' + file.name + '">')
uploadedDocumentMap[file.name] = response.name
},
removedfile: function (file) {
file.previewElement.remove()
var name = ''
if (typeof file.file_name !== 'undefined') {
name = file.file_name
} else {
name = uploadedDocumentMap[file.name]
}
$('form').find('input[name="document[]"][value="' + name + '"]').remove()
},
init: function () {
#if(isset($project) && $project->document)
var files =
{!! json_encode($project->document) !!}
for (var i in files) {
var file = files[i]
this.options.addedfile.call(this, file)
file.previewElement.classList.add('dz-complete')
$('form').append('<input type="hidden" name="document[]" value="' + file.file_name + '">')
}
#endif
}
}
</script>
Some things are not right in your code AND your concept (at least in my opinion):
You need to prevent the default behavior of the #btn because you need to intercept the form submission. Otherwise, the form will just get submitted as a GET request (what is the default behavior).
$("#btn").click(function (e) {
e.preventDefault();
// ...
}
The <form> element is not closed. Furthermore, don't override the _ token in your JavaScript but just add #csrf to the form. Larvel and jQuery will handle everything for you.
<form>
#csrf
I think I understood what you were trying to achieve now. Dropzone is uploading (= POST request) the files directly, so you need a separate route (or another code branch) to handle the file upload. Then, you can get the filename of the previously uploaded file and attach it as a hidden input field like so:
success: function (file, response) {
$('form').append('<input type="hidden" name="document[]" value="' + file.name + '">')
},
What you will receive in your controller's method is the pro_name, pro_price and an array document containing the names of the uploaded files. Following your logic, the file must be already existing in the storage because it was uploaded by the Dropzone action. You could then save the filename to the database or whatever and use it as a reference for accessing the file later.
Anyway, I would not recommend to use the client-provided filename for storage because it may not be unique. Laravel offers a lot of helpful tools for this scenario: https://laravel.com/docs/5.7/filesystem#file-uploads

Sending FormData with AngularJS [duplicate]

I want to pass the username and form_data object to the php file using http.post
when i pass only form_data it works my picture upload. but i want to pass some other information like username as well. please help me how to pass other data in http.post
And here is my php file.
<?php include "connectdb.php";
$data=json_decode(file_get_contents("php://input"));
$name=$dbhandle->real_escape_string($data->susername);
if (!empty($_FILES)) {
$date=2;
$path = 'fooditem/'. $_FILES['file']['name'];
if (move_uploaded_file($_FILES['file']['tmp_name'],$path)) {
$query="INSERT INTO `login`(`id`,`type`,`img`) VALUES('".$name."','".$date."','".$_FILES['file']['name']."')";
if($dbhandle->query($query)){
echo 'File Uploaded';
}
else
echo 'File Uploaded But Not Saved';
}
}else{
echo 'Some Error';
}
myapp.directive("fileInput",function($parse){
return{
link: function($scope,element,attrs){
element.on("change",function(event){
var files = event.target.files;
$parse(attrs.fileInput).assign($scope, element[0].files);
$scope.$apply();
// console.log(files[0].name);
});
}
}
});
myapp.controller("myController",function($scope,$http){
$scope.signup = function(){
var form_data = new FormData();
angular.forEach($scope.files,function(file){
form_data.append('file',file);
});
$http.post("picupload.php",{'susername':$scope.susername,form_data})
.then(function(response){
console.log(response);
})
});
<input type="text" ng-model="username" name="username">
<input type="file" file-input="files" accept="image/*" />
<input type="submit" value="SIGN UP" ng-click="signup()"
name="signup_btn" class="btn btn-primary">
You can add something like this:
myapp.controller("myController",function($scope,$http){
$scope.signup = function(){
var form_data = new FormData();
angular.forEach($scope.files,function(file){
form_data.append('file',file);
});
form_data.append('susername',$scope.susername); // new line
var config = {headers: { 'Content-type': undefined } };
$http.post("picupload.php",form_data, config)
.success(function(response){
alert(response);
});
}
I'm not sure about PHP but after googling I found that in php 'susername' can retrieved as below:
$_POST['susername'];
How to make POST requests with the FormData API
When posting objects created by the FormData API, it is important to set the Content-type header to undefined.
$scope.signup = function(){
var form_data = new FormData();
angular.forEach($scope.files,function(file){
form_data.append('file',file);
});
form_data.append('susername', $scope.susername);
var config = {headers: { 'Content-type': undefined } };
return $http.post("picupload.php",form_data, config)
.then(function(response){
console.log(response.data);
return response.data;
});
};
Also a FormData object can not be serialized into a JSON string it must be sent by the XHR API alone. Append all necessary data to the FormData object.
When the XHR send API posts an object created by the FormData API, it automatically sets the content type header to multipart/form-data with a proper encapsulation boundary and encodes the data using base64 encoding.
Normally the $http service overrides the XHR API sets the content type header to application/json. Setting the content type header to undefined allows the XHR API the freedom to set the header properly.
Update
On the server side use:
$_POST['susername'];
to receive the data item.

Image upload via ajax POST without using HTML form

I am trying to send some data via POST method to a PHP file without using form in HTML. This is the code I have. Why doesn't it do anything?
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="hidden" value="<?php echo $row['Gallery_Id']; ?>" name="gid" id="gid">
<input type="hidden" value="User" name="user" id="user">
<button onclick="myFormData()">Upload Image</button>
<script>
$('#fileToUpload').on('change', function() {
var myFormData = new FormData();
var file = document.getElementById('fileToUpload').value;
var gid = document.getElementById('gid').value;
var user = document.getElementById('user').value;
myFormData.append('file', file);
myFormData.append('gid', gid);
myFormData.append('user', user);
});
$.ajax({
url: 'imgupload.php',
type: 'POST',
processData: false, // important
contentType: false, // important
dataType : 'json',
data: myFormData
});
</script>
On imgupload.php I get the POST data like this
$gid = $_POST['gid'];
$user = $_POST['user'];
It worked when I used the HTML form method. What's wrong here?
FormData.append() takes key-value pairs, so this is wrong:
myFormData.append(file,gid,user);
You need something like:
myFormData.append('file', file);
myFormData.append('gid', gid);
myFormData.append('user', user);
Appart from that you need to put this code inside an event handler so that it triggers when you need it to.
For example:
$('#fileToUpload').on('change', function() {
// your javascript code
});
And you should probably also put it inside a document.ready block.

Save photo from user with AJAX and PHP

I have a problem with saving photos with Ajax and PHP.
This is my form in HTML
<form id="form3">
<input id="photo3" name="photo" class="form-control" type="file" id="fileInput3" />
</form>
And this is my JS
data = $("form#form3").serializeArray();
var file = $("#photo3")[0].files[0];
data.push({name: "photo", value: file});
$.ajax({
url: 'registrace.php',
data: data,
complete: function (response) {
alert(response.responseText);
},
error: function () {}
});
And this is PHP
$output = 'users/'.$namernd.'.jpg';
move_uploaded_file($_GET['photo'],$output);
Everything is copied to my database and works, but photo is not saved to my server.
Ok, i found solution. Just change to this:
var formdata = new FormData();
formdata.append('name', $('#name3'));
formdata.append('password', $('#password3'));
formdata.append('city', $('#city3'));
formdata.append('email', $('#email3'));
formdata.append('file', $('#photo3')[0].files[0]);
And
$namernd = uniqid();
$output = 'users/'.$namernd.'.jpg';
move_uploaded_file($_FILES["file"]["tmp_name"],$output);

AJAX Codeigniter - You did not select a file to upload(error)- How to pass the file through AJAX

I am trying to upload images via an AJAX call and Codeigniter:
My View:
<?php echo form_open_multipart('upload/do_upload'); ?>
<input type="file" name="userfile" id="userfile" size="20" />
<br />
<input type="submit" value="upload" id="upload_file_1" />
</form>
My Ajax Call:
$(document).ready(function(){
$(function() {
$('#upload_file_1').click(function(e) {
e.preventDefault();
var filename = $("#userfile").val();
$.ajax({
url :'index.php/upload/do_upload',
secureuri :false,
fileElementId: 'userfile',
dataType : 'json',
type : 'POST',
done : function (data)
{
alert(data);
}
});
});
});
});
and my controller:
class Upload extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->helper(array('form', 'url'));
}
function index() {
$this->load->view('upload_form', array('error' => ' '));
}
function do_upload() {
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '1000000';
$config['max_width'] = '10240';
$config['max_height'] = '7680';
$this->load->library('upload', $config);
if (!$this->upload->do_upload('userfile')) {
$error = array('error' => $this->upload->display_errors());
echo "error!";
echo "<pre>";
print_r($error);
echo "<pre/>";
} else {
echo "done!";
}
}
}
but it gives me an error saying : "You did not select a file to upload. "; without AJAX it works fine, probably my AJAX call is not right! Could you please let me know if I am doing something wrong?
Thanks
In my very recent project i used below code to upload files with formdata asynchronously using jquery ajax,
However i was not able to upload files with success: function() of jQuery so i used complete to process server response. You can try with success:function().
You will receive your data in $_Post & file in $_FILES variable.
If only want to upload files. change it like wise.
Hope this will help you.
Also look at this tutorial:http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax
function frm_submit(){
var form = new FormData(document.getElementById('frmSample')); //frmSample is form id
var file = document.getElementById('userfile').files[0]; //userfile file tag id
if (file) {
form.append('userfile', file);
}
$.ajax({
url: 'path/to/upload/script',
type: 'POST',
xhr: function() { // custom xhr
//progressHandlingFunction to hangle file progress
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // check if upload property exists
myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // for handling the progress of the upload
}
return myXhr;
},
data: form,
cache: false,
contentType: false, //must
processData: false, //must
complete: function(XMLHttpRequest) {
var data = JSON.parse(XMLHttpRequest.responseText);
console.log(data);
console.log('complete');
},
error: function() {
console.log('error');
}
}).done(function() {
console.log('Done Sending messages');
}).fail(function() {
console.log('message sending failed');
});
}//function frm_submit ends here
i used this javascript library
https://github.com/blueimp/jQuery-File-Upload
and got file uploading working with ajax - drag/drop + progress bars, and returns the appropriate file icon or image thumbnail that could be downloaded straight away. it was quite difficult to get it fully working and abstracted so the same routine handled multiple types of uploads each with their own restrictions.
the link will give some basic example code, it is worth a look.
pete

Categories

Resources