Laravel controller can't save files from ajax request - javascript

So I have problems with uploading my image files to controller via ajax. My partner suppose to have many images. I successfully sent my images to controller via ajax, but the files cannot be store to database for some reason. I tried to send back the files request back to console log and see only empty objects. Any solution, guys?
This is my form:
<form
id="kkpn-partnerImg-form"
method="POST"
enctype="multipart/form-data"
>
<input
id="kkpn-upload-file"
type="file"
name="partnerImg[]"
multiple
accept="image/*"
data-url="{{ route('partners.partner_upload_images.store', $partner->id) }}"
hidden
>
<button
class="btn btn-success"
id="kkpn-upload-btn"
>
Upload your images
</button>
</form>
This is my Javascript:
$(document).ready(function(){
$('#kkpn-upload-btn').on('click', openDialog)
function openDialog(){
document.getElementById('kkpn-upload-file').click();
}
$('#kkpn-partnerImg-form').on('submit', function(e){
e.preventDefault();
var formData = new FormData(this);
if ($('#kkpn-upload-file').get(0).files.length != 0) {
var uploadUrl = $('#kkpn-upload-file').data('url');
formData.append(
'_token',
$('meta[name="csrf-token"]').attr('content')
)
for (var pair of formData.entries()) {
console.log(pair[0]+ ', ' + pair[1]);
}
$.ajax(
{
url: uploadUrl,
type: 'POST',
data: formData,
cache:false,
contentType: false,
processData: false,
success: function(response){
console.log(response.data)
},
error: function(error){
console.log('Error Occured!')
}
}
)
}
})
$('#kkpn-upload-file').on('change', function(){
$('#kkpn-partnerImg-form').submit()
})
})
This is my controller:
public function store(Request $request, $id)
{
$partner = Partner::where('id', $id)->first();
foreach($request->file('partnerImg') as $fileImg){
$partnerImg = new PartnerImg;
$partnerImg->img_path = $fileImg->store('partners');
$partnerImg->partner()->associate($partner);
$partnerImg->save();
}
return response()->json([
'data' => $request->file('partnerImg')
]);
}
So it didn't give me any errors or anything, it just can't store the file and when i return my request with files, it gave me empty objects. If any one know how to solve this, please help!
And this is what I get after successfully response of ajax:

As you're uploading an array of files, have you attempted accessing them with
foreach($request->file('partnerImg[]') as $fileImg) {
in your controller?
Source: https://laracasts.com/discuss/channels/laravel/how-upload-multiple-files-using-ajax-in-laravel

For some reason, I delete everything and redo again! It works! Sorry guys! But thanks for suggestion!

first problem i have seen is that you are not passing the $id parameter on ajax
public function store(Request $request, $id)
{
$partner = Partner::find($id); //change to this!
foreach($request->file('partnerImg[]') as $fileImg){
$partnerImg = new PartnerImg;
$partnerImg->img_path = $fileImg->store('partners');
$partnerImg->partner()->associate($partner);
$partnerImg->save();
}
return response()->json([
'data' => $request->file('partnerImg[]')
]);
}

Related

I get an empty error when submitting multiple forms with file uploads with ajax in laravel

my problem is while posting multiple forms with ajax in laravel, I am sending the form data without any problem, but I cannot send the file.
File is empty error. I've been dealing with this for 2 days, there is no method I haven't tried, please help me.
Apart from that, I added multipart to the form, but it still didn't work, I'm sharing my codes with you.
Sorry for my bad english.
I want it to upload 2 photos in the normal 4th form until the createProduct3 form, I tried to get them by doing the normal new formData() and I tried otherwise and I couldn't succeed.
It sends it to Laravel server side as [Object File].
My Form
<form class="form" id="createProduct4" method="POST" action="">
<input type="file" class="upload-box-title" id="urun-fotografi" name="urun_fotografi" value="Fotoğraf Seç">
<input type="file" class="upload-box-title" id="urun-dosyasi" name="urun_dosyasi" value="Dosya Seç">
</form>
My blade ajax:
function createProducts()
{
var dataString = $("#createProduct1, #createProduct2, #createProduct3, #createProduct4").serialize();
let photo = document.getElementById("urun-dosyasi").files[0];
let photo2 = document.getElementById("urun-fotografi").files[0];
console.log(photo,photo2);
$.ajax({
url: "{{ route('user.product.create') }}",
type: "POST",
data: dataString+"&urun_dosyasi="+photo+"&urun_fotografi="+photo2,
success: function( data ) {
},
error: function(xhr)
{
console.log(xhr);
}
});
}
Server Function
public function createProduct(Request $request)
{
$file = $request->file('urun_dosyasi');
$file2 = $request->file('urun_fotografi');
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$filename2 = $file2->getClientOriginalName();
$extension2 = $file2->getClientOriginalExtension();
echo $filename,$extension."2. doc: ".$filename2.$extension;
}
Use multipart/form-data when your form includes any <input type="file"> elements :
<form ... enctype="multipart/form-data">
Ajax :
var form = $('#createProduct4')[0];
var data = new FormData(form);
$.ajax({
url: "{{ route('user.product.create') }}",
type: "POST",
enctype: 'multipart/form-data',
data: data,
processData: false,
contentType: false,
success: function (data) {
console.log("SUCCESS : ", data);
},
error: function (e) {
console.log("ERROR : ", e);
}
});

Processing AJAX data array via PHP - no $_POST occuring? [duplicate]

I'm using jQuery and Ajax for my forms to submit data and files but I'm not sure how to send both data and files in one form?
I currently do almost the same with both methods but the way in which the data is gathered into an array is different, the data uses .serialize(); but the files use = new FormData($(this)[0]);
Is it possible to combine both methods to be able to upload files and data in one form through Ajax?
Data jQuery, Ajax and html
$("form#data").submit(function(){
var formData = $(this).serialize();
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="data" method="post">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<button>Submit</button>
</form>
Files jQuery, Ajax and html
$("form#files").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="files" method="post" enctype="multipart/form-data">
<input name="image" type="file" />
<button>Submit</button>
</form>
How can I combine the above so that I can send data and files in one form via Ajax?
My aim is to be able to send all of this form in one post with Ajax, is it possible?
<form id="datafiles" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
The problem I had was using the wrong jQuery identifier.
You can upload data and files with one form using ajax.
PHP + HTML
<?php
print_r($_POST);
print_r($_FILES);
?>
<form id="data" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
jQuery + Ajax
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
});
Short Version
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function(data) {
alert(data);
});
});
another option is to use an iframe and set the form's target to it.
you may try this (it uses jQuery):
function ajax_form($form, on_complete)
{
var iframe;
if (!$form.attr('target'))
{
//create a unique iframe for the form
iframe = $("<iframe></iframe>").attr('name', 'ajax_form_' + Math.floor(Math.random() * 999999)).hide().appendTo($('body'));
$form.attr('target', iframe.attr('name'));
}
if (on_complete)
{
iframe = iframe || $('iframe[name="' + $form.attr('target') + '"]');
iframe.load(function ()
{
//get the server response
var response = iframe.contents().find('body').text();
on_complete(response);
});
}
}
it works well with all browsers, you don't need to serialize or prepare the data.
one down side is that you can't monitor the progress.
also, at least for chrome, the request will not appear in the "xhr" tab of the developer tools but under "doc"
I was having this same issue in ASP.Net MVC with HttpPostedFilebase and instead of using form on Submit I needed to use button on click where I needed to do some stuff and then if all OK the submit form so here is how I got it working
$(".submitbtn").on("click", function(e) {
var form = $("#Form");
// you can't pass Jquery form it has to be javascript form object
var formData = new FormData(form[0]);
//if you only need to upload files then
//Grab the File upload control and append each file manually to FormData
//var files = form.find("#fileupload")[0].files;
//$.each(files, function() {
// var file = $(this);
// formData.append(file[0].name, file[0]);
//});
if ($(form).valid()) {
$.ajax({
type: "POST",
url: $(form).prop("action"),
//dataType: 'json', //not sure but works for me without this
data: formData,
contentType: false, //this is requireded please see answers above
processData: false, //this is requireded please see answers above
//cache: false, //not sure but works for me without this
error : ErrorHandler,
success : successHandler
});
}
});
this will than correctly populate your MVC model, please make sure in your Model, The Property for HttpPostedFileBase[] has the same name as the Name of the input control in html i.e.
<input id="fileupload" type="file" name="UploadedFiles" multiple>
public class MyViewModel
{
public HttpPostedFileBase[] UploadedFiles { get; set; }
}
Or shorter:
$("form#data").submit(function() {
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function() {
// success
});
return false;
});
EDIT: with the new version of JQuery (3.6), you could also try using contentType function argument instead of enctype. Try contentType: multipart/form-data.
For me, it didn't work without enctype: 'multipart/form-data' field in the Ajax request. I hope it helps someone who is stuck in a similar problem.
Even though the enctype was already set in the form attribute, for some reason, the Ajax request didn't automatically identify the enctype without explicit declaration (jQuery 3.3.1).
// Tested, this works for me (jQuery 3.3.1)
fileUploadForm.submit(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: $(this).attr('action'),
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
console.log('Thank God it worked!');
}
}
);
});
// enctype field was set in the form but Ajax request didn't set it by default.
<form action="process/file-upload" enctype="multipart/form-data" method="post" >
<input type="file" name="input-file" accept="text/plain" required>
...
</form>
As others mentioned above, please also pay special attention to the contentType and processData fields.
A Simple but more effective way:
new FormData() is itself like a container (or a bag). You can put everything attr or file in itself.
The only thing you'll need to append the attribute, file, fileName eg:
let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)
and just pass it in AJAX request. Eg:
let formData = new FormData()
var d = $('#fileid')[0].files[0]
formData.append('fileid', d);
formData.append('inputname', value);
$.ajax({
url: '/yourroute',
method: 'POST',
contentType: false,
processData: false,
data: formData,
success: function(res){
console.log('successfully')
},
error: function(){
console.log('error')
}
})
You can append n number of files or data with FormData.
and if you're making AJAX Request from Script.js file to Route file in Node.js beware of using
req.body to access data (ie text)
req.files to access file (ie image, video etc)
The code below works for me
$(function () {
debugger;
document.getElementById("FormId").addEventListener("submit", function (e) {
debugger;
if (ValidDateFrom()) { // Check Validation
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
debugger;
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function (result) {
debugger;
if (xhr.readyState == 4 && xhr.status == 200) {
debugger;
var responseData = JSON.parse(xhr.responseText);
SuccessMethod(responseData); // Redirect to your Success method
}
};
xhr.send(new FormData(form));
}
}
}
}, true);
});
In your Action Post Method, pass parameter as HttpPostedFileBase UploadFile and make sure your file input has same as mentioned in your parameter of the Action Method.
It should work with AJAX Begin form as well.
Remember over here that your AJAX BEGIN Form will not work over here since you make your post call defined in the code mentioned above and you can reference your method in the code as per the Requirement
I know I am answering late but this is what worked for me
Just to remind, in 2022 you don't need to use jquery. Try js standard Fetch API
var formData = new FormData(this);
fetch(url, {
method: 'POST',
body: formData
})
.then(response => {
if(response.ok) {
//success
alert(response);
} else {
throw Error('Server error');
}
})
.catch(error => {
console.log('fail', error);
});
This is a solution that I implemented
var formData = new FormData();
var files = $('input[type=file]');
for (var i = 0; i < files.length; i++) {
if (files[i].value == "" || files[i].value == null) {
return false;
}
else {
formData.append(files[i].name, files[i].files[0]);
}
}
var formSerializeArray = $("#Form").serializeArray();
for (var i = 0; i < formSerializeArray.length; i++) {
formData.append(formSerializeArray[i].name, formSerializeArray[i].value)
}
$.ajax({
type: 'POST',
data: formData,
contentType: false,
processData: false,
cache: false,
url: '/Controller/Action',
success: function (response) {
if (response.Success == true) {
return true;
}
else {
return false;
}
},
error: function () {
return false;
},
failure: function () {
return false;
}
});
---Solution for DOT NET CORE MVC Implementation---
While looking at this question I though I should right .NET CORE implementation for this because the question is not specific to any backend language.
So guys here is the standalone implementation example.
Objective :- To submit form fields including files and how we can get data in a single model at backend
HTML Code / View Code - Views/Home/Index.cshtml
#{
ViewData["Title"] = "Home Page";
}
<input type="file" id="FileUpload1" multiple />
<div>
<label>Enter First Name :</label>
<input type="text" id="nameText" maxlength="50" />
</div>
<input type="button" id="btnUpload" value="Submit Form with Files" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('#btnUpload').click(function () {
// Checking whether FormData is available in browser
if (window.FormData !== undefined) {
var fileUpload = $("#FileUpload1").get(0);
var files = fileUpload.files;
// Create FormData object
var fileData = new FormData();
// Looping over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append("files", files[i]);
}
// Adding one more key to FormData object
fileData.append('FirstName', $("#nameText").val());
$.ajax({
url: '/Home/UploadFiles',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
} else {
alert("FormData is not supported.");
}
});
});
</script>
Backend Code / Controller action method Controllers/HomeController.cs
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IWebHostEnvironment _environment;
public HomeController(ILogger<HomeController> logger, IWebHostEnvironment environment)
{
_logger = logger;
_environment = environment;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UploadFiles(MyForm myForm)
{
var files = myForm.Files;
// First Name
string name = myForm.FirstName;
// check All files
foreach (IFormFile source in files)
{
string filename = ContentDispositionHeaderValue.Parse(source.ContentDisposition).FileName.Trim('"');
filename = this.EnsureCorrectFilename(filename);
string fileWithPath = this.GetPathAndFilename(filename);
// Create directory if not exist
Directory.CreateDirectory(Path.GetDirectoryName(fileWithPath));
using (FileStream output = System.IO.File.Create(fileWithPath))
await source.CopyToAsync(output);
}
return Ok("Success");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public class MyForm
{
public string FirstName { get; set; }
public IList<IFormFile> Files { get; set; }
}
private string EnsureCorrectFilename(string filename)
{
if (filename.Contains("\\"))
filename = filename.Substring(filename.LastIndexOf("\\") + 1);
return filename;
}
private string GetPathAndFilename(string filename)
{
return Path.Combine(_environment.ContentRootPath, "uploadedFiles", filename);
}
}
Full Source Code Repo: https://github.com/rj-learning/DotNetCoreFileUpload
In my case I had to make a POST request, which had information sent through the header, and also a file sent using a FormData object.
I made it work using a combination of some of the answers here, so basically what ended up working was having this five lines in my Ajax request:
contentType: "application/octet-stream",
enctype: 'multipart/form-data',
contentType: false,
processData: false,
data: formData,
Where formData was a variable created like this:
var file = document.getElementById('uploadedFile').files[0];
var form = $('form')[0];
var formData = new FormData(form);
formData.append("File", file);
you can just append them on your formdata, add your files and datas in it.you can read this..
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
for better understanding. you can separately retrieve them $_FILES for your files and $_POST for your data.
<form id="form" method="post" action="otherpage.php" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button type='button' id='submit_btn'>Submit</button>
</form>
<script>
$(document).on("click", "#submit_btn", function (e) {
//Prevent Instant Click
e.preventDefault();
// Create an FormData object
var formData = $("#form").submit(function (e) {
return;
});
//formData[0] contain form data only
// You can directly make object via using form id but it require all ajax operation inside $("form").submit(<!-- Ajax Here -->)
var formData = new FormData(formData[0]);
$.ajax({
url: $('#form').attr('action'),
type: 'POST',
data: formData,
success: function (response) {
console.log(response);
},
contentType: false,
processData: false,
cache: false
});
return false;
});
</script>
///// otherpage.php
<?php
print_r($_FILES);
?>

Ajax upload not working codeigniter

I am using codeigniter 3.1 . I want to post upload data using ajax.
Ajax upload file not working. But when i post the simple form without ajax, it working fine.
I don't know why but no error in console.
HTML
<?php echo form_open_multipart(site_url("upload/post"), ['id' => 'uploader']) ?>
<input type="file" name="userfile" value="">
<input type="submit" value="Submit" />
<?php echo form_close() ?>
JAVASCRIPT
$('#uploader').submit(function (event) {
event.preventDefault();
$.ajax({
url: window.location.href + '/post',
type: "POST",
dataType: 'json',
data: new FormData(this)
});
});
CONTROLLERS
public function post()
{
$this->load->helper('url');
$this->load->helper('form');
$this->load->library("upload");
$file = $this->common->nohtml($this->input->post("userfile"));
$this->upload->initialize(array(
"upload_path" => 'upload',
"overwrite" => FALSE,
"max_filename" => 300,
"encrypt_name" => TRUE
));
$this->upload->do_upload('userfile');
$data = $this->upload->data();
$image_file = $data['file_name'];
}
Another approach to this would be passing to PHP the file encoded in base64:
get the selected file from #userfile field using $('#userfile').prop('files')[0];
transform the contents of that file into a base64 encoded string using FileReader.readAsDataURL(). We're going to call this content; Here's a similar question showing how to do and expanding the answer & possibilities;
send the AJAX passing both the filename and content strings;
now on CI, fetch the POST data;
base64_decode() the content;
fwrite() the result into a file using the filename.
That way also you could avoid POSTing all form fields.
try this..
Post data using FormData() formdata post file also.
To get all your form inputs, including the type="file" you need to use FormData object.
$('#post').on('click', function (e) {
var file_data = $("#userfile").prop("files")[0];
var form_data = new FormData();
form_data.append("userfile", file_data)
$.ajax({
url: window.location.href+'/post',
type: 'POST',
data: form_data,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
For more...https://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax
One of the issues is that file uploading uses a different mechanism than the other form <input> types. That is why $this->input->post("userfile") isn't getting the job done for you. Other answers have suggested using javascript's FormData and this one does too.
HTML
A very simple form for picking a file and submitting it. Note the change from a simple button to <input type="submit".... Doing so makes it a lot easier for the javascript to use the FormData object.
FormData documentation
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="https://code.jquery.com/jquery-2.2.2.js"></script>
<title>Upload Test</title>
</head>
<body>
<?= form_open_multipart("upload/post", ['id' => 'uploader']); ?>
<input type="file" name="userfile">
<p>
<input type="submit" value="Upload">
</p>
<?php echo form_close() ?>
<div id="message"></div>
<script>
$('#uploader').submit(function (event) {
event.preventDefault();
$.ajax({
url: window.location.href + '/post',
type: "POST",
dataType: 'json',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
console.log(data);
if (data.result === true) {
$("#message").html("<p>File Upload Succeeded</p>");
} else {
$("#message").html("<p>File Upload Failed!</p>");
}
$("#message").append(data.message);
}
});
});
</script>
</body>
</html>
JAVASCRIPT
Use FormData to capture the fields.
Note that instead of handling the button click we handle the submit event.
$('#uploader').submit(function (event) {
event.preventDefault();
$.ajax({
url: window.location.href + '/post',
type: "POST",
dataType: 'json',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
//uncomment the next line to log the returned data in the javascript console
// console.log(data);
if (data.result === true) {
$("#message").html("<p>File Upload Succeeded</p>");
} else {
$("#message").html("<p>File Upload Failed!</p>");
}
$("#message").append(data.message);
}
});
});
CONTROLLER
I've added some code that "reports" results to ajax and will display it on the upload page.
class Upload extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->helper(['form', 'url']);
}
public function index()
{
$this->load->view('upload_v');
}
public function post()
{
$this->load->library("upload");
$this->upload->initialize(array(
"upload_path" => './uploads/',
'allowed_types' => 'gif|jpg|png|doc|txt',
"overwrite" => FALSE,
"max_filename" => 300,
"encrypt_name" => TRUE,
));
$successful = $this->upload->do_upload('userfile');
if($successful)
{
$data = $this->upload->data();
$image_file = $data['file_name'];
$msg = "<p>File: {$image_file}</p>";
$this->data_models->update($this->data->INFO, array("image" => $image_file));
} else {
$msg = $this->upload->display_errors();
}
echo json_encode(['result' => $successful, 'message' => $msg]);
}
}
This will upload your file. Your work probably isn't done because I suspect that your are not saving all the file info you need to the db. That, and I suspect you are going to be surprised by the name of the uploaded file.
I suggest you study up on how PHP handles file uploads and examine some of the similar codeigniter related questions on file uploads here on SO.
Controller
public function upload()
{
$this->load->library('upload');
if (isset($_FILES['myfile']) && !empty($_FILES['myfile']))
{
if ($_FILES['myfile']['error'] != 4)
{
// Image file configurations
$config['upload_path'] = './upload/';
$config['allowed_types'] = 'jpg|jpeg|png';
$this->upload->initialize($config);
$this->upload->do_upload('myfile');
}
}
}
View
<form id="myform" action="<?php base_url('controller/method'); ?>" method="post">
<input type="file" name="myfile">
("#myform").submit(function(evt){
evt.preventDefault();
var url = $(this).attr('action');
var formData = new FormData($(this)[0]);
$.ajax({
url: url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function (res) {
console.log(res);
},
error: function (error) {
console.log(error);
}
}); // End: $.ajax()
}); // End: submit()
Let me know if any query
you need to submit the form not on click but on submit ... give the form an id and then on submit put ajax
HTML
<?php $attributes = array('id' => 'post'); ?>
<?php echo form_open_multipart(site_url("upload/post",$attributes), ?>
<input type="file" id="userfile" name="userfile" value="">
<button id="post">Submit</button>
<?php echo form_close() ?>
JAVASCRIPT
$('#post').on('submit', function () {
var formData = new FormData();
formData.append("userfile",$("#userfile")[0].files[0]);
$.ajax({
url: window.location.href+'/post',
type: "POST",
data: formData
});
CONTROLLERS
public function post()
{
$this->load->library("upload");
$file = $this->common->nohtml($this->input->post("userfile"));
$this->upload->initialize(array(
"upload_path" => 'upload',
"overwrite" => FALSE,
"max_filename" => 300,
"encrypt_name" => TRUE,
));
$data = $this->upload->data();
$image_file = $data['file_name'];
$this->data_models->update($this->data->INFO, array(
"image" => $image_file
)
);
}

Correct way to pass data to Jquery Ajax

Whats the correct way to pass data to ajax using jquery. I have the following method and I want to pass the CSRF token from a meta tag but it doesn't work.
<meta name="csrf-token" content="{{ csrf_token() }}">
<div class="fallback">
<input type="file" name="logo" id="logo" class="inputfile"/>
</div>
$(document).on("change", ".fallback .inputfile", function() {
$.ajax({
url: "/upload",
type: 'POST',
cache: false,
data: {
_token: $('meta[name="csrf-token"]').attr('content')
},
files: $(":file", this),
iframe: true,
processData: false
}).complete(function(data) {
console.log(data);
// $('#img-thumb').attr('src', data.path);
// $('input[name="job_logo"]').val(data.path);
});
});
Laravel method to process the file:
public function upload(Request $request) {
if($request->hasFile('logo')) {
//upload an image to the /img/tmp directory and return the filepath.
$file = $request->file('logo');
$tmpFileName = time() . '-' . $file->getClientOriginalName();
$tmpFilePath = '/img/tmp/';
$file = $file->move(public_path() . $tmpFilePath, $tmpFileName);
$path = $tmpFilePath . $tmpFileName;
return response()->json(['path'=> $path], 200);
} else {
return response()->json(false, 200);
}
}
I've followed the documentation from the following source https://cmlenz.github.io/jquery-iframe-transport/
I get tokenmismatch error. Note this is using Laravel 5.1
* UPDATE *
Should be able to add the token directly to data attribute as the csrf token is already in my meta tag. Below is an example done using backbone.js/ruby on rails, but I'm not an expert on backbone/rails so if any one can translate that into jquery it would be helpful. (http://estebanpastorino.com/2013/09/27/simple-file-uploads-with-backbone-dot-js/)
uploadFile: function(event) {
var values = {};
var csrf_param = $('meta[name=csrf-param]').attr('content');
var csrf_token = $('meta[name=csrf-token]').attr('content');
var values_with_csrf;
if(event){ event.preventDefault(); }
_.each(this.$('form').serializeArray(), function(input){
values[ input.name ] = input.value;
})
values_with_csrf = _.extend({}, values)
values_with_csrf[csrf_param] = csrf_token
this.model.save(values, { iframe: true,
files: this.$('form :file'),
data: values_with_csrf });
}
processData: false
You've told jQuery to not convert the object containing your data into a format suitable for transmitting over HTTP.
You need to add this to your page:
$(function() {
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN' : '{{ csrf_token() }}' } });
});
This is because the AJAX needs the X-CSRF-TOKEN everytime you send an AJAX request to the server (unless you turn it off, which I don't recommend).
SOURCE: my own experiences with Laravel.

Ajax search - Laravel

I am trying to create a live search using jquery, ajax and laravel. I also use pjax on the same page, this might be an issue?. Quite simply it should query the database and filter through results as they type.
When using Ajax type:POST I am getting 500 errors in my console. I get zero errors using GET but instead of returning in #foreach it will a full page view (this might be because of pjax).
Where am I going wrong?
Route:
Route::post('retailers/{search}', array(
'as' => 'search-retailers', 'uses' => 'RetailersController#search'));
Controller:
public function search($keyword) {
if(isset($keyword)) {
$data = array('store_listings' => RetailersListings::search($keyword));
return $data;
} else {
return "no results";
}
}
Model:
public static function search($keyword)
{
$finder = DB::table('retailers_listings')
->Where('city', 'LIKE', "%{$keyword}%")
->orWhere('country', 'LIKE', "{$keyword}")
->orderBy('country', 'asc')
->get();
return $finder;
}
View (store.blade.php):
<div id="flash"></div> //loading
<div id="live"> // hide content
<div id="searchword"><span class="searchword"></span></div> //search word
<table class="table">
<tbody>
#foreach($store_listings as $store)
<tr>
<td></td> //echo out all fields eg: {{ $store->name }}
</tr>
#endforeach
</tbody>
</table>
</div>
Form:
<form method="get" action="">
<input type="text" class="search-retailers" id="search" name="search">
</form>
Ajax and JS:
$(function() {
$("#search").keyup(function() {
var keyword = $("#search").val();
var dataString = 'keyword='+ keyword;
if(keyword=='') {
} else {
$.ajax({
type: "GET",
url: "{{ URL::route('search-retailers') }}",
data: dataString,
cache: false,
beforeSend: function(html)
{
document.getElementById("live").innerHTML = '';
$("#flash").show();
$("#keyword").show();
$(".keyword").html(keyword);
$("#flash").html('Loading Results');
},
success: function(html)
{
$("#live").show();
$("#live").append(html);
$("#flash").hide();
}
});
} return false;
});
});
Additional, Here is my controller for pjax, It is important to note I am using the view store.blade.php foreach in for the search and for this store listing.
public function stores($city)
{
$this->layout->header = $city;
$content = View::make('retailers.stores', with(new RetailersService())->RetailersData())
->with('header', $this->layout->header)
->with('store_listings', RetailersListings::stores($city));
if (Request::header('X-PJAX')) {
return $content;
} else {
$this->layout->content = $content;
}
}
Your route is Route::post('retailers/{search}', [...]) and there you go. You pass data to your ajax-call. In GET you get something like url?key=value but using POST the data are added to the request body not to the url.
Knowing this your route is no longer valid since it only looks up for retailers/{search} and not for retailers only (which is the url POST is using).
Well maybe it could help somebody.
As a first problem you are defining the route as POST and then in the ajax request the type GET so it would not work
Also when making POST request Laravel has the csrf check so in order to work, provide it. The js function will be like
$(function() {
$("#search").keyup(function() {
var keyword = $("#search").val();
if(keyword=='') {
} else {
$.ajax({
type: "post",
url: "{{ URL::route('search-retailers') }}",
data: {
'keyword': keywork,
'_token': '{{ csrf_token() }}';
},
dataType: 'html',
cache: false,
beforeSend: function(html)
{
document.getElementById("live").innerHTML = '';
$("#flash").show();
$("#keyword").show();
$(".keyword").html(keyword);
$("#flash").html('Loading Results');
},
success: function(html)
{
$("#live").show();
$("#live").append(html);
$("#flash").hide();
}
});
} return false;
});
});
And you can test your PHP search method doing separate tests for it.

Categories