I'm trying to implement dropzone.js into my CakePHP application. So far it all went fine. Except When I receive an error, it displays the whole HTML error page, not rendered. Which turns into a bunch of HTML code, not quite readable and because the error box becomes so big I cannot click the "remove" button. See picture below:
As soon as I receive an error:
When I hover the box, after receiving an error:
I know the reason is that dropzone.js recognizes the error because of the 500 header of the Ajax page (I throw an Exception if something goes wrong). And CakePHP renders a complete layout for a 500 error page. So it's not possible for me to just view a one row error. And I really need the 500 header, because else dropzone.js thinks everything went fine....
So my question: Is it possible to NOT render the 500 error layout, when getting a 500 error within a specific Controller method? I don't want to completely disable the 500 error layout rendering. Only for AJAX pages.
public function admin_add($slug = null) {
if(!$slug || !$client = $this->Video->Client->find('first', array('conditions' => array('slug' => $slug)))) {
throw new NotFoundException(__('Invalid client'));
}
if ($this->request->is('post')) {
// If request contains files, continue
if (!empty($_FILES)) {
// Get slug from URL
$slug = substr( $this->referer(), strrpos( $this->referer(), '/' )+1 );
// Create new folder for the movies if it doesn't exist already
if (!file_exists(WWW_ROOT.'/files/'.$slug)) {
mkdir(WWW_ROOT.'/files/'.$slug, 0777, true);
}
$tempFile = $_FILES['file']['tmp_name'];
$targetPath = '/files/'.$slug.'/';
$targetFile = $targetPath. $_FILES['file']['name'];
// Create variable filename without the extension
$fileWithoutExt = preg_replace("/\\.[^.\\s]{3,4}$/", "", $_FILES['file']['name']);
// Add file to Video array
$video['Video'] = array('video' => $targetFile, 'screenshot' => '/files/'.$slug.'/screenshots/'.$fileWithoutExt.'.jpg', 'client_id' => $client['Client']['id']);
// unset($video);
// Try moving the file to their final directory
if(!move_uploaded_file($tempFile, WWW_ROOT.$targetFile)) {
throw new NotFoundException(__('Move image to "'.WWW_ROOT.$targetPath.'" failed'));
}
// Create new folder for the screenshots if it doesn't exist already
if (!file_exists(WWW_ROOT.'/files/'.$slug.'/screenshots/')) {
mkdir(WWW_ROOT.'/files/'.$slug.'/screenshots/', 0777, true);
}
// Try saving video to Video table in the database
if(!$this->Video->save($video)){
throw new NotFoundException(__('Failed connecting client with "'.$targetFile.'" in the database'));
}
}
$this->Session->setFlash(__('Videos successfully uploaded'), 'default', array(), 'success');
$this->redirect($this->referer());
}
$title_for_layout = $client['Client']['name'];
$this->set(compact('title_for_layout', 'client'));
}
You can change retuned status code by use statusCode method of CakeResponse class. Something like this: $this->response->statusCode(404);
It's a little not correct to use NotFoundException to return http status code. At least you can create your own application exception
Please, check Creating your own application exceptions
You will easily to define one exceptions:
class MissingWidgetException extends CakeException {};
And after that you can use it and send http status code which you need Creating custom status codes :
throw new MissingWidgetHelperException('Its not here', 501);
501 is http status code.
Hope, this will help to find out right solution.
Related
I'm trying to make a POST request with params in terms of a file upload and user text upon user clicking Submit. However, I keep getting a failed response via the dd(); (which's coming from the API endpoint I've received) for some reason even though I get the file upload success message defined by the flash. What am I doing wrong in my controller?
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Zttp\Zttp;
class FileUploadController extends Controller {
public function index(){
return view('view/index');
}
public function uploadFile(Request $request) {
$userText = $request->input('userText'); // grabbing text area input that user inputs
if ($request->input('submit') != null ){
$file = $request->file('file'); // file user wants to upload
// File Details
$filename = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$fileSize = $file->getSize();
// Valid File Extensions
$valid_extension = ["jpg", "jpeg", "png", "bmp"];
// 10MB in Bytes
$maxFileSize = 10485760;
// Check file extension
if(in_array(strtolower($extension),$valid_extension)) {
// Check file size
if($fileSize <= $maxFileSize){
$request->session()->flash('message','Upload Successful.');
$response = Zttp::post("https://myendpoint.com/upload.php", [
'one' => 'some text',
'two', 'some other text',
'three' => $filename,
'four' => $userText
]);
$responseJson = $response->json(); // parses json response into an array for you
dd($responseJson);
} else {
$request->session()->flash('message','File too large. File must be less than 2MB.');
}
} else {
$request->session()->flash('message','Invalid File Extension.');
}
}
// Redirect to index
return redirect()->action('FileUploadController#index');
}
}
The question is a bit of a red herring. It's not your controller giving the failed response. Whatever's going on at the endpoint is living in a seperate request and the error lives there.
Additionally – your flash message declares the upload successful before your controller posts anything to your endpoint.
<?php
// ...
$request->session()->flash('message','Upload Successful.');
$response = Zttp::post("https://myendpoint.com/upload.php", [/* */]);
I reccommend you parse the $response more thoroughly and only set the flash message if the response code is 2XX.
Any debugging re: a failed response at that endpoint will rely on more info, including the response itself, and the nature of the endpoint. (Is it also yours? A third party API?)
I'm writing an app that lets the user upload an Excel file. It checks the file for errors, then, if no errors are found, it uploads the contents to a database. If it does find errors, the cells containing errors are colored red, then the file is saved. I then want to create a download link to this file so the user can check where they made mistakes.
The problem is that I am not sure how to create this link and where to store the file. I modify the file like this:
foreach ($badCells as $bcell) {
$sheet->getStyle($bcell)->applyFromArray(array(
'fill' => array(
'type' => \PHPExcel_Style_Fill::FILL_SOLID,
'color' => array('rgb' => 'FF4444')
)
));
}
And then save it with
$objWriter->save($dldir . $formData['upload']['name']);
$dldir is created with
$dldir = "/download/";
if (file_exists($dldir)) {
if (!is_dir($dldir)) {
unlink($dldir);
mkdir($dldir);
}
} else {
if(!is_dir($dldir)) {
mkdir($dldir);
}
}
Is this even the right way to do this? Can I store the files in any old folder or do they have go somewhere specific? How do I create the link to the specific file in the view for the user and make it accessible so they can download it?
I may be wrong .
For file upload i use this library Gargron/fileupload
The function bellow help to upload file to a specific folder and return full link of the file. You can save the link in DB
function uploadFile ($file){
$validator = new \FileUpload\Validator\Simple('5M');
$pathresolver = new \FileUpload\PathResolver\Simple($_SERVER['DOCUMENT_ROOT'].'/upload_folder');
$filesystem = new \FileUpload\FileSystem\Simple();
$fileupload = new \FileUpload\FileUpload(file, $_SERVER);
$fileupload->setPathResolver($pathresolver);
$fileupload->setFileSystem($filesystem);
$fileupload->addValidator($validator);
$md5Generator = new \FileUpload\FileNameGenerator\MD5 (true);
$fileupload->setFileNameGenerator($md5Generator);
list($files) = $fileupload->processAll();
foreach($files as $file){
if ($file->completed) {
return $_SERVER['DOCUMENT_ROOT'].'/upload_folder/'.$file->getFileName()) ;
}
}
}
Thanks for the help, I managed to figure it out over the weekend. Here's how I did
it:
$filename = join(DIRECTORY_SEPARATOR, array($dldir, $formData['upload']['name']));
$objWriter->save(str_replace(__FILE__,$filename,__FILE__));
This is how I save the file, using DIRECTORY_SEPARATOR so it will work correctly on both Windows and Linux.
return $this->redirect()->toRoute('import', ['action' => 'reject'],['query' => ['q' => 'file', 'name' => $filename]]);
In the controller, I redirect the route to the correct action and pass the file name on to it via a query URL.
public function rejectAction()
{
$filename = $this->getRequest()->getQuery('name', null);
return new ViewModel(array('filename' => $filename));
}
There, I obtain said file name through getRequest()->getQuery() and pass it on to the viewmodel.
Right-click here and choose 'Save As' to download your file.
And finally, this is how it shows the link in reject.phtml.
Downloading only works with right click and save as, I suspect I will have to write some sort of file handler to make ZF produce the correct headers for a normal left click download.
this might be a bit of a novice question and here is my situation:
i have a upload form for uploading images. and in my editAction i do:
if ($request->isPost()) {
if (isset($_POST['upload_picture']) && $formImageUpload->isValid($_POST)) {
//here i will add the picture name to my database and save the file to the disk.
}
}
$picVal = $this->getmainPic(); // here i do a simple fetch all and get the picture that was just uploaded
$this->view->imagepath = $picVal;
what happens is that the newly uploaded picture doesn't show. I checked the database and the dick and the file is there.
im thinking the problem might be the order of the requests or something similar.
any ideas?
edit: another thing is that in order to make the new image come up i have to do a SHIFT+F5 and not only press the browser refresh button
edit2: more code
i first call the upload to disk function then if that returns success addthe file to the database
$x = $this->uploadToDiskMulty($talentFolderPath, $filename)
if($x == 'success'){
$model->create($data);
}
the upload function
public function uploadToDiskMulty($talentFolderPath, $filename)
{
// create the transfer adapter
// note that setDestiation is deprecated, instead use the Rename filter
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addFilter('Rename', array(
'target' => $filename,
'overwrite' => true
));
// try to receive one file
if ($adapter->receive($talentFolderPath)) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}
If the picture only appears when you do SHIFT+F5 that means it's a caching problem. Your browser doesn't fetch the image when you upload it. Do you use the same file name?
I have been working on a little MVC project to assist in my self-learning and I have come across an issue that completely baffled me. I made a blog section in this MVC-ish system and pulled user permissions from an ACL with no problem whatsoever.
I moved onto creating a member section and as soon as i added any permissions checking I get the following error from Chrome:
No data received
Unable to load the web page because the server sent no data.
Here are some suggestions:
Reload this web page later.
Error 324 (net::ERR_EMPTY_RESPONSE): The server closed the connection without sending any data.
I thought it was weird, so I double checked my error logs and nothing had shown up. So I decided to copy and paste the working blog code into the member file, reloaded and i got the EXACT same error, the only difference between the two files right now is the file name and the class name.
Here is the Blog code:
<?php
class blog extends frontController {
public $model;
public $user;
public function __construct()
{
parent::__construct();
$this->model = $this->autoload_model();
$this->user = $this->load_user();
$this->user->getUserRoles();
}
public function index()
{
//Will only list the latest post ;)
if(!$this->user->hasPermission('blog_access'))
{
$array = $this->model->list_posts();
if(empty($array))
{
$this->variables(array(
'site_title' => 'View Blog Posts',
'post_title' => 'Sorry but there are no posts to display'
));
} else {
$this->variables(array(
'site_title' => 'View Blog Posts',
'list' => $array[0],
'post_title' => $array[0]['entry_title'],
'link' => str_replace(' ', '_',$array[0]['entry_title']),
));
}
} else {
$this->variables(array(
'site_title' => 'Error :: Design Develop Realize',
'body' => 'Sorry, but you do not have permission to access this',
));
}
$this->parse('blog/list', $this->toParse);
}
This is the member file:
<?php
class member extends frontController {
public $model;
public $user;
public function __construct()
{
parent::__construct();
$this->model = $this->autoload_model();
$this->user = $this->load_user();
$this->user->getUserRoles();
}
public function index()
{
//Will only list the latest post ;)
if(!$this->user->hasPermission('blog_access'))
{
//$array = $this->model->list_posts();
if(empty($array))
{
$this->variables(array(
'site_title' => 'Design Develop Realize :: View Blog Posts',
'post_title' => 'Sorry but there are no posts to display'
));
} else {
$this->variables(array(
'site_title' => 'Design Develop Realize :: View Blog Posts',
'list' => $array[0],
'post_title' => $array[0]['entry_title'],
'link' => str_replace(' ', '_',$array[0]['entry_title']),
));
}
} else {
$this->variables(array(
'site_title' => 'Error :: Design Develop Realize',
'body' => 'Sorry, but you do not have permission to access this',
));
}
$this->parse('blog/list', $this->toParse);
}
In the member class, if I comment out $this->user = $this->load_user(); then the error disappears!!!
Just for reference here is that function:
protected function load_user()
{
if(!$this->loader->loaded['acl'])
{
$this->loader->loadCore('acl');
}
return $this->loader->loaded['acl'];
}
Any help or suggestions would be appreciated as I am stumped!
PS yes I do have error reporting set to cover everything and no it does not log anything!
EDIT: Because all files go through index.php I have placed the error reporting there:
<?php
error_reporting(E_ALL);
ini_set('date.timezone', "Europe/London");
require_once('system/library/loader.php');
$loader = new loader();
$loader->loadCore(array('frontController', 'routing'));
EDIT 2: loadCore() is below
public function loadCore($toLoad, $params = false)
{
//important task first, check if it is more then 1 or not
if(is_array($toLoad))
{
//more then one so lets go to the task!
foreach($toLoad as $file)
{
if(file_exists('system/library/' . $file . '.php'))
{
require_once('system/library/' . $file . '.php');
if($params)
{
$this->loaded[$file] = new $file($params);
} else {
$this->loaded[$file] = new $file;
}
} else {
trigger_error("Core File $file does not exist");
}
}
} else {
//Phew, less work, it is only one!
if(file_exists('system/library/' . $toLoad . '.php'))
{
require_once('system/library/' . $toLoad . '.php');
if($params)
{
echo(__LINE__); exit;
$this->loaded[$toLoad] = new $toLoad($params);
} else {
$this->loaded[$toLoad] = new $toLoad;
}
}
}
}
Update: I modified loadCore so that if it was the acl being called it would use a try...catch() and that has not helped as it will not display an error just the same chrome and IE pages
Update 2: I have spoken with my host and it seems that everytime this error occurs, apache logs the following (not sure why I cannot see it in my copy of the logs!)
[Wed Feb 22 08:07:11 2012] [error] [client 93.97.245.13] Premature end
of script headers: index.php
You have commented out
//$array = $this->model->list_posts();
So now array is null and you are trying to use
'list' => $array[0],
'post_title' => $array[0]['entry_title'],
which definitely will generate an error.
EDIT:-
I see you have
'body' => 'Sorry, but you do not have permission to access this' , )); }
That is in second else which is a syntax error. and generates an output. If you have enabled, compress output in CI, that will cause this error.
"Premature end of script headers" are internal server errors. Which generally occurs when script breaks and does not send any HTTP headers before send the error messages. There might be several causes to this.
One might be output buffering. May be the server you are using buffers the output by default. I will suggest turning off the output_buffering using output_buffering = off on php.ini [docs here].
Make sure you are sending correct HTTP headers also
print "Content-type: text/html\n\n";
There are few more suggestion on this link.
To learn more about this error, go here.
Hope it helps
I'd be interested in seeing what's inside the loadCore function.
Have you used error_log anywhere? It might help shed some light on the issue.
Have you tested this page in different browsers? Googled your error, and it's indicating that it may be chrome specific?
Your statement that commenting out the loadCore('acl') is interesting, so obviously I would start there. You're sure that it is getting the system/library/acl.php page via the loader? Aka, it is triggering that line 2 below the exit in loadCore()? var_dump the return imo to make sure you're getting the object.
First of all. This error is produced when your server disconnect before it send any data.
A few suggestions.
your code is broken and let crash the application
your error logging should be enhanced by NOTICES
write tests to check every part
u should enable and use a debugger (zend_debugger, xdebug)
post a few more connection infos (e.g. wget -O - --debug 'url')
There is/was a special chrome issue for that problem
http://www.google.pl/support/forum/p/Chrome/thread?tid=3aa7b40eb01a95c8&hl=en#fid_3aa7b40eb01a95c80004ae797939c267
I suggest checking whether there are any blank lines before the tags.
What file names are you using?, are there any conventions you have to follow to fit a framework you might be using?
I wonder if this is a server problem and not a code problem?
This thread suggests that the server error you are seeing (500 premature end to headers) could be the result of Apache logs that are too full and need to be rotated. However it really could be anything - it seems to suggest simply that the script returns no output at all to the browser.
The other thing I'd check is file permissions, and the functioning of the include_once and file_exists in the loadCore method, as that looks the likeliest area to cause problems that might stop the script without even throwing a php error.
Maybe it´s a character/encoding error, open both files with notepad++ , goto Encoding, then select Convert to UTF-8, save the file and test it again.
Good Luck!
I want to upload an image with Zend Framework version 1.9.6. The uploading itself works fine, but I want a couple of other things as well ... and I'm completely stuck.
Error messages for failing to upload an image won't show up.
If a user doesn't enter all the required fields but has uploaded an image then I want to display the uploaded image in my form. Either as an image or as a link to the image. Just some form of feedback to the user.
I want to use Zend_ Validate_ File_ IsImage. But it doesn't seem to do anything.
And lastly; is there some automatic renaming functionality?
All ideas and suggestions are very welcome. I've been struggling for two days now.
These are simplified code snippets:
myform.ini
method = "post"
elements.title.type = "text"
elements.title.options.label = "Title"
elements.title.options.attribs.size = 40
elements.title.options.required = true
elements.image.type = "file"
elements.image.options.label = "Image"
elements.image.options.validators.isimage.validator = "IsImage"
elements.submit.type = "submit"
elements.submit.options.label = "Save"
TestController
<?php
class Admin_TestController extends Zend_Controller_Action
{
public function testAction ()
{
$config = new Zend_Config_Ini(MY_SECRET_PATH . 'myform.ini');
$f = new Zend_Form($config);
if ($this->_request->isPost())
{
$data = $this->_request->getPost();
$imageElement = $f->getElement('image');
$imageElement->receive();
//$imageElement->getValue();
if ($f->isValid($data))
{
//save data
$this->_redirect('/admin');
}
else
{
$f->populate($data);
}
}
$this->view->form = $f;
}
}
?>
My view just echo's the 'form' variable.
First, put this at the start of your script:
error_reporting(E_ALL);//this should show all php errors
I think the error messages are missing from the form because you re-populate the form before you display it. I think that wipes out any error messages. To fix that, remove this part:
else
{
$f->populate($data);
}
To show the uploaded image in the form, just add a div to your view template, like this:
<div style="float:right"><?=$this->image?></div>
If the image uploaded ok, then populate $view->image with an img tag.
As for automatic re-naming, no, it's not built in, but it's very easy. I'll show you how below.
Here's how I handle my image uploads:
$form = new Zend_Form();
$form->setEnctype(Zend_Form::ENCTYPE_MULTIPART);
$image = new Zend_Form_Element_File('image');
$image->setLabel('Upload an image:')
->setDestination($config->paths->upload)
->setRequired(true)
->setMaxFileSize(10240000) // limits the filesize on the client side
->setDescription('Click Browse and click on the image file you would like to upload');
$image->addValidator('Count', false, 1); // ensure only 1 file
$image->addValidator('Size', false, 10240000); // limit to 10 meg
$image->addValidator('Extension', false, 'jpg,jpeg,png,gif');// only JPEG, PNG, and GIFs
$form->addElement($image);
$this->view->form = $form;
if($this->getRequest()->isPost())
{
if(!$form->isValid($this->getRequest()->getParams()))
{
return $this->render('add');
}
if(!$form->image->receive())
{
$this->view->message = '<div class="popup-warning">Errors Receiving File.</div>';
return $this->render('add');
}
if($form->image->isUploaded())
{
$values = $form->getValues();
$source = $form->image->getFileName();
//to re-name the image, all you need to do is save it with a new name, instead of the name they uploaded it with. Normally, I use the primary key of the database row where I'm storing the name of the image. For example, if it's an image of Person 1, I call it 1.jpg. The important thing is that you make sure the image name will be unique in whatever directory you save it to.
$new_image_name = 'someNameYouInvent';
//save image to database and filesystem here
$image_saved = move_uploaded_file($source, '/www/yoursite/images/'.$new_image_name);
if($image_saved)
{
$this->view->image = '<img src="/images/'.$new_image_name.'" />';
$form->reset();//only do this if it saved ok and you want to re-display the fresh empty form
}
}
}
First, have a look at the Quick Start tutorial. Note how it has an ErrorController.php that will display error messages for you. Also note how the application.ini has these lines to cause PHP to emit error messages, but make sure you're in the "development" environment to see them (which is set in public/.htaccess).
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
Second, ZF has a renaming filter for file uploads:
$upload_elt = new Zend_Form_Element_File('upload');
$upload_elt
->setRequired(true)
->setLabel('Select the file to upload:')
->setDestination($uploadDir)
->addValidator('Count', false, 1) // ensure only 1 file
->addValidator('Size', false, 2097152) // limit to 2MB
->addValidator('Extension', false, 'doc,txt')
->addValidator('MimeType', false,
array('application/msword',
'text/plain'))
->addFilter('Rename', implode('_',
array($this->_user_id,
$this->_upload_category,
date('YmdHis'))))
->addValidator('NotExists', false, $uploadDir)
;
Some of the interesting things above:
mark the upload as required (which your .ini doesn't seem to do)
put all the uploads in a special directory
limit file size and acceptable mime types
rename upload to myuser_category_timestamp
don't overwrite an existing file (unlikely, given our timestamp scheme, but let's make sure anyway)
So, the above goes in your form. In the controller/action that receives the upload, you could do this:
$original_filename = $form->upload->getFileName(null, false);
if ($form->upload->receive()) {
$model->saveUpload(
$this->_identity, $form->upload->getFileName(null, false),
$original_filename
);
}
Note how we capture the $original_filename (if you need it) before doing receive(). After we receive(), we do getFileName() to get the thing that the rename filter picked as the new filename.
Finally, in the model->saveUpload method you could store whatever stuff to your database.
Make sure your view also outputs any error messages that you generate in the controller: loading errors, field validation, file validation. Renaming would be your job, as would other post processing such as by image-magick convert.
When following lo_fye's listing I experienced problems with custom decorators.
I do not have the default File Decorator set and got the following exception:
Warning: Exception caught by form: No file decorator found... unable to render file element Stack Trace:
The Answer to this is that one of your decrators must implement the empty interface Zend_Form_Decorator_Marker_File_Interface
Also sometimes it happens to bug when using an ajax request. Try it without an ajax request and don't forget the multipart form.