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?)
Related
I receive all user activities for each image upload they make, but I also want to receive the image in this foreach along with the table.
In my database I have 5 columns within the users table, which are doc1 doc2 doc3 doc4 and doc5. As I receive the image made by them together with the correct description, without having to log in to each user account
in fact there are 5 controllers of these, please don't notice the mess ^^ I'm new to programming
public function mudar_doc1(Request $request) {
// getting all of the post data
$file = array('image' => Input::file('image'));
// setting up rules
$rules = array('image' => 'required|image',); //mimes:jpeg,bmp,png and for max size max:10000
// doing the validation, passing post data, rules and the messages
$validator = Validator::make($file, $rules);
if ($validator->fails()) {
// send back to the page with the input data and errors
return Redirect::to('userp')->withInput()->withErrors($validator);
} else {
// checking file is valid.
if (Input::file('image')->isValid()) {
$destinationPath = 'uploads'; // upload path
$extension = Input::file('image')->getClientOriginalExtension(); // getting image extension
$extensoes = array("png", "jpeg", "jpg", "gif");
$resVal = in_array($extension, $extensoes);
if ($resVal) {
} else {
Session::flash('error', 'O upload não foi realizado com sucesso.');
return Redirect::to('userp');
}
$fileName = rand(11111, 99999) . '.' . $extension; // renameing image
Input::file('image')->move($destinationPath, $fileName); // uploading file to given path
$doc1 = asset($destinationPath . '/' . $fileName);
User::where('id', \Auth::user()->id)->update(['doc1' => $doc1]);
// sending back with message
Session::flash('success', 'ID Card Front Successfully Added!');
\App\RegistroAtividade::addAtividade('Cartao ID Frente');
return Redirect::to('userp');
} else {
// sending back with error message.
Session::flash('error', 'O upload não foi realizado com sucesso.');
return Redirect::to('userp');
}
}
}
<tbody>
#foreach($allAtividades as $atividade)
<tr>
<td>{{$atividade['id']}}</td>
<td>{{$atividade->getUser()->name}}</td>
<td>{{$atividade['ip']}}</td>
<td>{{$atividade['description']}}</td>
<td>{{$atividade['created_at']}}</td>
</tr>
</tbody>
#endforeach
I don't see much reference in your code for the Image / controller / view or data, please update your question and i will update this answer along
Some important note I would like to make
I would suggest you spare some time reading about the Eloquent Relations
Then you can create the Actividade Eloquent if you don't have it already
In Actividade Eloquent you can assign a user relations like so
Class Actividade {
//...
public function user(){
return $this->belongsTo(App\User::class, 'user_id');
}
}
The user method here will return the user by using the user_id column in the actividade table [if you have it set up correctly already], that will make it easier to fetch the user for activities $actividade->user->name, instead of $actividade->getUser()->name;
following this approach you can have an ImagesEloquent class having activities method which is relational just like activities having users and users having activities:
using this approach (skeleton) would be as easy as this:
#foreach(Image::find(1)->activities as $_activity){
<td><img src="{{Image::find(1)->filename}}"/></td> <!-- just an example here -->
<td>{{$_activity->id}}</td>
<td>{{$_activity->user->name}}</td>
<td>{{$_activity->ip}}</td>
<td>{{$_activity->description}}</td>
<td>{{$_activity->created_at}}</td>
#endforeach
You fetch the Image, you can fetch it's activities, and then each activity has users
It will take a bit of time (an hour or so) to learn about this, but will save you hundreds of hours in the future and get you a way cleaner code, i thought to suggest that.
in this case I want to safe upload pdf, doc, docx, ppt, pptx, xls, xlsx, rar, zip prevent from arbitrary file upload especially web shell or any evil script.
The problem is how I can validate file, is safe to upload? prevent from bypass like change mime type with tamper data, rename file with multiple extension, using ; and space in file name, lowercase and uppercase file extension and etc.
my controller code look like this
public function fileUpload(){
$ext = ['pdf', 'doc', 'ppt', 'xls', 'docx', 'pptx', 'xlsx', 'rar', 'zip'];
$data = Request::all();
$name = $data['file']->getClientOriginalName();
$rules = [
'file' => 'required'
];
$v = Validator::make($data, $rules);
if($v->passes()){
// Check safe file validation
// should here or something? and how to prevent bypass
// arbitrary file upload especially evil script.
$data['file']->move(public_path('assets/uploads'), $name);
return 'file uploaded';
}else{
return 'file upload failed';
}
}
I would suggest looking at Laravel Middleware for the validation. This will reduce the code in your controllers and allow them to be reused.
I personally change the name of any file upload to something random. I can always save the original file name somewhere in the system if needs be.
I would also look at using a htaccess command which prevents file execution from that folder.
Controller method below
Note: it uses App\Http\Requests\CreateUploadRequest;
public function store(CreateUploadRequest $request)
{
$file = Input::file('file');
$destinationPath = 'assets/uploads'; // upload path
$name = $file->getClientOriginalName(); // getting original name
$fileName = time().rand(11111, 99999) . '.' . $extension; // renaming image
$extension = $file->getClientOriginalExtension(); // getting fileextension
$file->save($destinationPath.'/'.$fileName); // uploading file to given path
}
Middleware
<?php namespace App\Http\Requests;
use App\Http\Requests\Request;
class CreateUploadRequest extends Request {
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'file' => 'required_if:update,false|mimes:pdf,doc,ppt,xls,docx,pptx,xlsx,rar,zip|max:1000'
];
}
}
I think this idea was taken from a laracast video. I'll have a look around to see if i can find it.
I need to send an image to server via an ajax request and it gets through just fine
and in my controller I can just use $_FILES["image"] to do stuff to it.
But I need to validate the image before I save it.
And in the Yii this can be achieved by doing something like this
$file = CUploadedFile::getInstance($model,'image');
if($model->validated(array('image'))){
$model->image->saveAs(Yii::getPathOfAlias('webroot') . '/upload/user_thumb/' . $model->username.'.'.$model->photo->extensionName);
}
But the problem is I don't have a $model, all I have is $_FILES["image"], now what should I put instead of the $model???
is there any other way where I can validate and save files without creating a model and just by Using $_FILES["image"]?
thanks for this awesome community... :)
Exists many ways how you can do upload. I want offer to you one of them.
1.You need to create model for your images.
class Image extends CActiveRecord {
//method where need to specify validation rules
public function rules()
{
return [
['filename', 'length', 'max' => 40],
//other rules
];
}
//this function allow to upload file
public function doUpload($insName)
{
$file = CUploadedFile::getInstanceByName($insName);
if ($file) {
$file->saveAs(Yii::getPathOfAlias('webroot').'/upload/user_thumb/'.$this->filename.$file->getExtensionName());
} else {
$this->addError('Please, select at least one file'); // for example
}
}
}
2.Now, need to create controller, where you will do all actions.
class ImageController extends CController {
public function actionUpload()
{
$model = new Image();
if (Yii::app()->request->getPost('upload')) {
$model->filename = 'set filename';
$insName = 'image'; //if you try to upload from $_FILES['image']
if ($model->validate() && $model->doUpload($insName)) {
//upload is successful
} else {
//do something with errors
$errors = $model->getErrors();
}
}
}
}
Creating a model might be overkill in some instances.
The $_FILE supervariable is part of the HTTP mechanism.
You can handle the copy by using the native PHP function move_uploaded_file()
$fileName = "/uploads/".myimage.jpg";
unlink($fileName);
move_uploaded_file($_FILES['Filedata']['tmp_name'], $fileName);
However, you lose the niceties of using a library that provides additional functionality and checks (eg file type and file size limitations).
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.
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?