I am working in Zend Framework 1 and I have this function in a controller:
public function uploadAction()
{
$this->_helper->layout->disableLayout();
$this->_helper->viewRenderer->setNoRender();
$data = [];
if ($this->getRequest()->isPost()) {
$path = /cronjobs/uploads';
// Clean $path directory OOP way using SPL
$di = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($ri as $file) {
$file->isDir() ? rmdir($file) : unlink($file);
}
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator('Extension', false, ['extension' => 'csv', 'case' => true]);
$adapter->addValidator('MimeType', false, ['extension' => 'text/plain']);
// Check if the uploaded file is valid
$errors[] = $adapter->isValid() === false ? $adapter->getMessages() : '';
$file = (array) $adapter->getFileInfo()['file'];
$ext = end(explode('.', $file['name']));
$new_path = $file['tmp_name'];
// Check file size
$checkFileSize = Attachment::checkMaxfileSize($file['size']);
if (!$checkFileSize['accept']) {
echo json_encode($checkFileSize['message']);
return true;
}
$data['file'] = array(
'name' => $file['name'],
'size' => $adapter->getFileSize(),
'file_path' => $new_path,
'file_ext' => $ext
);
$data['var'] = '';
} else {
$data['error'] = 'Invalid request.';
}
return $this->_helper->json($data);
}
This method is called trough AJAX as follow:
$('#fileupload').show().fileupload({
url: url,
type: "POST",
cache: false,
dataType: 'json',
done: function (e, data) {
console.log(data.result);
},
error: function (xhr, textStatus, errorThrown) {
console.log(xhr + " " + textStatus + " " + errorThrown);
}
})
For some reason as soon as I call $adapter->isValid() in the controller the AJAX response gets break. I can say the problem is there because if I comment that piece of code everything works fine.
This is the message I am getting currently:
POST http://localhost/admin/upload net::ERR_EMPTY_RESPONSE
massive_charge_types_file_upload.js:147 [object Object] error
After read all of the following topics:
net::ERR_EMPTY_RESPONSE when post with ajax
Getting ERR_EMPTY_RESPONSE on $.POST
PHP Jquery Ajax call throws net::ERR_EMPTY_RESPONSE
and many more in Google
I am out of ideas and I am stuck since can't find what's causing the behavior.
UPDATE:
I believe the problem is on the isValid() method which return a boolean but for some reason this is breaking my response. Any ideas?
Can any help me with this?
It seems the syntax of your MimeType validator is wrong:
$adapter->addValidator('MimeType', false, ['extension' => 'text/plain']);
Should probably be:
$upload->addValidator('MimeType', false, array('text/plain'));
As described:
https://framework.zend.com/manual/1.12/en/zend.file.transfer.validators.html
Since your file won't pass the (impossible) validation test - I am guessing this is what then leads to no results?
After a few tries I got it working by adding the following:
if ($adapter->isValid() === false) {
$data['error'][] = $adapter->getMessages();
echo json_encode($data);
return true;
}
I need to use raw json_encode() PHP function, if I use the Zend Framework JSON helper as for example: $this->_helper->json($data) the response didn't work.
I believe this is a restriction for the Jquery plugin not sure tough.
Related
I'm new to php and stuck in my tracks here, so any help is appreciated. I've written a few functions in a JS file to render and update a gallery view for a WordPress template I made. From the updateGallery() function, I make an AJAX call after pressing a submit button on the page, but am receiving a "parsererror."
Arguments(3) [{…}, "parsererror", SyntaxError: Unexpected token A in JSON at position 0 at parse (<anonymous>)
at Ut (https://…, callee: ƒ, Symbol(Symbol.iterator): ƒ]
I tried the code for the API request directly in my WP template to render a response and it worked as expected, but when I try to incorporate my script I get the error and I can't figure out what's causing it.
JS
function updateGallery() {
var county = $("#county").val();
jQuery(".galleryGrid").fadeOut("fast", function() {
console.log("ajax request");
jQuery(".galleryGrid").html("").hide();
$.ajax({
type : "GET",
dataType : "JSON",
url : ajax.url,
data : {
action: "get_gallery_data",
county_id : county
},
error: function(response, error) {
console.log(arguments);
alert("Failed because: " + error);
},
success : function(response) {
if(response.type === "success") {
console.log("Success")
renderGrid(response.data);
}
}
});
});
}
PHP
add_action("wp_ajax_nopriv_get_gallery_data", "get_gallery_data");
add_action("wp_ajax_get_gallery_data", "get_gallery_data");
function get_gallery_data() {
$county_id = $_REQUEST[county_id];
$base_api_url = "https://some.api.com/";
$filters = array(
"field" => "field_153",
"operator" =>"is",
"value" => $county_id
);
$filters_url = rawurlencode(json_encode($filters));
$api_url = $base_api_url."?filters=".$filters_url;
$request = wp_remote_get($api_url, array(
"headers" => array(
"Application-Id" => "5xxxxxx",
"REST-API-KEY" => "0xxxxxx",
),
));
$body = wp_remote_retrieve_body($request);
$output = json_decode($body, true);
echo $output;
die();
};
$output = json_decode($body, true);
//Change
$output = json_encode($body, true);
this is my view code working on auto complete , but its showing me 500 internal server error
I am not sure what is going wrong if i'm not using the right url or some other problem.
public function search(){
$this->loadComponent('RequestHandler');
if ($this->request->is('ajax'))
{
$name = $this->request->query['term'];
$resultArr = $this->Invoices
->find()
->where(
['Invoices.name LIKE' => ($name . '%')],
['Invoices.name' => 'string']);
$resultsArr = [];
foreach ($resultArr as $result)
{
$resultsArr[] = ($result['name']);
}
$this->set('resultsArr', $resultsArr);
// This line is what handles converting your array into json
// To get this to work you must load the request handler
$this->set('_serialize', ['resultsArr']);
}
}
this is my view code:
<?php echo $this->Form->input('name', ['type' => 'text']); ?>
$.ajax({
type: "POST",
url: "<?php echo Router::url(array('controller' => 'Clinics','action' => 'search')); ?>",
success: function(response) {
$("#name").autocomplete({ source: response });
}
});
According to the error message in your comments, the loadComponent method isn't defined.
I would suggest loading the RequestHandler component near the top of your controller, for example:
class ClinicController extends AppController {
public $components = array('Request');
There is also another syntax for loading components on the fly:
$this->Request = $this->Components->load('Request');
Reference: https://book.cakephp.org/2.0/en/controllers/components.html
I'm using laravel 4.2 and currently I don't how to save a csv file into public\csv\ directory using AJAX. I'm still finding some answers. Maybe someone can help me with this.
Here's my code:
In blade view:
{{Form::open(['route' => 'file_upload', 'files' => true, 'id' => 'upload_form', 'method' => 'POST'])}}
{{Form::file('csv_upload', ['id' => 'uploaded_file', 'accept' => 'text/csv'])}}
{{Form::submit('submit', ['class' => 'btn btn-primary btn-xs', 'id' => 'upload'])}}
{{Form::close()}}
Javascript Ajax:
var ajax_ready = 1
var token = {{Session::get('_token')}}
if($.type(originalOptions.data) === 'string') {
options.data = originalOptions.data+"&_token="+token;
}else if($.type(originalOptions.data) === 'object') {
//Here I got a new error
}else{
options.data = $.param(($.extend(originalOptions.data, {'_token':mmad_token})));
}
options.url = originalOptions.url.slice(0,originalOptions.url.indexOf("?_token="));
if (ajax_ready!=1){
jqXHR.abort();
}
ajax_ready = 0;
});
$('form#upload_form').on('submit', function(e){
e.preventDefault();
var uploadFile = $('#uploaded_file');
var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
var file = $('input[name="csv_upload"]').val();
if($.inArray(ext, ["csv"]) === -1) {
alert("Please upload a .csv file!");
return false;
}
var csv = uploadFile[0].files;
var form = new FormData(this);
var csvFile = {lastModifed: csv[0].lastModified, fileName: csv[0].name, size: csv[0].size, fileType: csv[0].type};
$.post('{{ URL::route("file_upload") }}?_token={{Session::token()}}',{
data: form
}).done(function(response){
});
});
PHP:
public function upload_csv()
{
$inputs = Input::all();
$csvFile = $inputs['data']['fileName'];
$path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
$path2 = public_path('csv/');
if(is_dir($path2))
{
#move_uploaded_file($csvFile, $path2.$csvFile); //This line can't move the uploaded files in my desired directory
}
return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);
}
This code below does work when not using AJAX:
if(Input::hasFile('csv_upload'))
{
$file = Input::file('csv_upload');
$originalFilename = $file->getClientOriginalName();
$rules = ['csv_upload' => 'required|file:csv'];
$validate = Validator::make(['csv_upload' => $file], $rules);
if($validate->fails())
{
return json_encode(['error' => 1, 'description' => 'File must be in .csv format']);
}
$path = public_path('/csv/');
if(!file_exists($path))
{
mkdir($path);
}
}
Console.log of csv
You can not move file because when you submit form with ajax file is not being sent with ajax,For sending file you have to send file with FormData() javascript Object.
If you check in upload_csv controller by putting print_r($_FILES); you will get empty array.
So use FormData on client side for appending file, then try agian.
You aren't getting error beacuse you have used php Error Control Operators likes#move_uploaded_file($csvFile, $path2.$csvFile);.
if you need working example then tell me i will give it to you.
Code For Your Help:
1. In blade view:
<script type="text/javascript">
$('form#upload_form').on('submit', function(e){
e.preventDefault();
var uploadFile = $('#uploaded_file');
var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
var file = $('input[name="mmad_csv_upload"]').val();
if($.inArray(ext, ["csv"]) === -1) {
alert("Please upload a .csv file!");
return false;
}
var csv = uploadFile[0].files;
var formData = new FormData($(this)[0]);
formData.append('uploaded_file', $("#uploaded_file")[0].files[0]);
formData.append('lastModifed', csv[0].lastModified);
formData.append('fileName', csv[0].name);
console.log(formData);
$.ajax({
url: '{{ URL::route("file_upload") }}',
type: 'POST',
data: formData,
async: true,
cache: false,
contentType: false,
processData: false,
success: function (returndata) { //alert(returndata); return false;
}
});
});
</script>
2.Controller
public function file_upload(Request $request)
{
$inputs = Input::all();
$csvFile = $inputs['fileName'];
$path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
$path2 = public_path('/csv/');
if(is_dir($path2))
{
$success = $request->file('uploaded_file')->move($path2, $csvFile);
}
return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);
}
To move the uploaded file to a new location, you should use the move method. This method will move the file from its temporary upload location (as determined by your PHP configuration) to a more permanent destination of your choosing:
Input::file('fileName')->move($destinationPath, $fileName);
If you need additional validations, you can check it at http://laravel.com/docs/5.1/requests#files
Default AJAX POST does not support file uploads. Use jQuery Form to upload files successfully. Full documentation of file upload at http://malsup.com/jquery/form/#file-upload
Below my example of a recentlty build script... My Controller uploads the files to S3, but is easy to be implemented with local storage.
var progress = function(event, position, total, percent) {
$(".progress-bar").width(percent + '%');
$(".progress-bar").html(percent + '%');
if(percent > 50) {
$(".progress-bar").css('color','#fff');
}
if(percent == 100) {
setTimeout(function(){
$(".progress").html('<span class="processing-msg">Processing... Please be patient!</span>');
$(".processing-msg").fadeIn('slow');
}, 1000);
}
}
var success = function(data) {
var obj = $.parseJSON(data);
$("#"+obj.hidden, parent.document).val(obj.filename);
var src = 'https://s3.amazonaws.com/spincms'+obj.path+'thumb_'+obj.filename;
$("#uploaded-"+obj.hidden, parent.document).html('<img class="img-circle uploaded-img" src="' + src + '">');
$(".progress").html('<span class="processing-msg-next">File has been uploaded and processed. Do not forget to submit the form!</span>');
}
var options = {
target: '#output',
uploadProgress: progress,
success: success,
resetForm: true
};
$(document).on('click', "#upload-now", function(e) {
$(".progress").html('<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>');
if($("#upload-form input[type=file]")[0].files.length == 0) {
$(".progress").html('<span class="processing-msg-next">No file selected!</span>');
return false;
} else {
var name = $("#upload-form input[name='name']").val();
var token = $("#upload-form input[name='_token']").val();
var file_name = $("#upload-form input[type=file]")[0].files[0].name;
$("#upload-form").ajaxSubmit(options);
}
}
});
Since you are using jQuery you can use the form plugin as it will make things much more easier for you to work with for example , this is the jquery part that you will use :
$(document).ready(function() {
// bind 'myForm' and provide a simple callback function
$('#upload_form').ajaxForm(function() {
alert("Your file has been uploaded, thanks");
});
});
and in your controller you can code it like :
pubilc function postUpload()
{
$success = false;
if(Request::ajax())
{
if(Input::hasFile('csv_upload'))
{
$file = Input::file('csv_upload');
if(!File::isDirectory(storage_path('csv'))) {
File::createDirectory(storage_path('csv'));
}
$file->move(storage_path('csv'), $file->getClientOriginalName());
// now your file is on app/storage/csv folder
$filePath = storage_path('csv/'.$file->getClientOriginalName());
$success = true;
}
}
return Response::json(['success'=>$success]);
}
I am using AJAX file upload with PHP (and Laravel).
After the file is uploaded (it's a CSV), the script processes it then it should return an array.
Route::post('uploadcsv', 'CSVController#uploadCSV');
class CSVController extends \BaseController {
public function processFile($filePath, $fileType)
{
// return 'test'; // works
Excel::load($filePath, function($reader)
{
return 'test'; // returns empty
$results = $reader->get();
return $results; // returns empty too
});
}
public function uploadCSV()
{
$user = Auth::user();
if (Input::hasFile('importCSV') && Input::file('importCSV')->isValid())
{
$file = Input::file('importCSV');
$extension = $file->getClientOriginalExtension();
if ($extension === 'csv' || $extension === 'txt')
{
$name = $user->username . '_' . time() . '.' . $extension;
$file->move(public_path() . '/uploads/', $name);
}
else
{
return 'fail';
}
}
else
{
return 'fail';
}
$processFileResponse = $this->processFile(public_path() . '/uploads/' . $name, $extension);
return $processFileResponse;
}
}
My AJAX looks like:
$('#importCSVSubmit').on('click', function () {
var formElement = document.getElementById('importCSVForm');
var formData = new FormData(formElement);
$.ajax({
type: 'POST',
url: 'uploadcsv',
data: formData,
processData: false,
contentType: false,
success: function (response, textStatus, xhr) {
console.log(response);
console.log(textStatus); // returns 'success'
console.log(xhr.error.length); // returns 0
}
});
});
However, when I'm using the code in the function processFile directly and load a demo page directly, it works and I can see the results of the Excel::load function.
The path ($filePath) is proper in every cases (working demo and non-working "ajax/php".)
You can see the lines with // return 'test'; and their comments, I used for trying to debug.
I'm guessing scope could be the problem, played around with that too (declared $results as global before the Excel::load())
I only had to declare global $results; inside processFile and inside Excel::load() and then I could return $results at the end of the processFile function.
public function processFile($filePath, $fileType)
{
global $results;
Excel::load($filePath, function($reader)
{
global $results;
$results = $reader->get();
});
return $results;
}
I am facing trouble while posting JSON DATA to recess framework. The JSON data posted perfect from the browser end. But when i get that from the server end it becomes null. I don't know the reason.
SMPLE EXT JS CODE:
Ext.Ajax.request({
url : 'http://localhost:8888/index.php' ,
method: 'POST',
jsonData: { dining: {name: 'test',},},
success: function ( result, request ) {
alert(result.responseText);
},
});
I can get the JSON data when i am using CORE PHP. But the issue was when im with RECESS FRAMEWORK.
Finally I found the answer after deep googling. Thanks to Hirnhamster the user, http://forums.recessframework.org/.
Solution
The solution is - in contrast to finding the real problem - rather easy:
1. Step:
Open the file DefaultPolicy.class.php in recess/recess/framework.
Go to method preprocess(..).
Add the line $this->reparameterizeForFormat($request); as last command before returning.
The function should now look like this:
<?php
public function preprocess(Request &$request) {
$this->getHttpMethodFromPost($request);
$this->forceFormatFromResourceString($request);
$this->reparameterizeForFormat($request);
return $request;
}
?>
2. Step
In the same file, go to method forceFormatFromResourceString(...).
Change the line $format = substr($lastPart, $lastDotPosition + 1); to $format = strtolower(substr($lastPart, $lastDotPosition + 1));
Add the line $request->format = $format; below if($format !== '') {
The function should now look like this:
<?php
protected function forceFormatFromResourceString(Request &$request) {
$lastPartIndex = count($request->resourceParts) - 1;
if($lastPartIndex < 0) return $request;
$lastPart = $request->resourceParts[$lastPartIndex];
$lastDotPosition = strrpos($lastPart, Library::dotSeparator);
if($lastDotPosition !== false) {
$format = strtolower(substr($lastPart, $lastDotPosition + 1));
if($format !== '') {
$request->format = $format;
$mime = MimeTypes::preferredMimeTypeFor($format);
if($mime !== false) {
$request->accepts->forceFormat($format);
$request->setResource(substr($request->resource, 0, strrpos($request->resource, Library::dotSeparator)));
}
}
}
return $request;
}
?>
3. Step
In the same file, go to method reparameterizeForFormat(...).
(Be astonished that this function already exists :P).
Change Format::JSON to "json" and Format::XML to "xml"
The function should now look like this:
<?php
protected function reparameterizeForFormat(Request &$request) {
if($request->format == "json") {
$method = strtolower($request->method);
$request->$method = json_decode($request->input, true);
} else if ($request->format == "xml") {
// TODO: XML reparameterization in request transformer
}
return $request;
}
?>
4. Step
You are done.
For Detailed Solution:
http://webcache.googleusercontent.com/search?q=cache:http://forums.recessframework.org/topic/189-json-request-doesnt-insert-values-in-v02/
Try:
Ext.Ajax.request({
url : 'http://localhost:8888/index.php' ,
method: 'POST',
jsonData: { dining: {name: 'test'} },
success: function( result, request ) {
alert(result.responseText);
}
});
You're writing Javascript. Some "commas" after } aren't valid.