I'm having trouble moving uploaded files, the problem seems to be a permissions problem, any help would be much appreciated. I'm using windows 10 and I've change my temp folder in php.ini to a custom folder in xampp directory and when I check this temp folder the file isn't there either, so it seems that it isn't even being uploaded to them temp. Please help.
class PortfolioItem extends DataBaseCommonObj{
protected static $table_name = 'portfolio_item';
protected static $db_fields = array('id','filename','mimetype','size','caption','job_id');
public $id;
public $filename;
public $mimetype;
public $size;
public $caption;
public $job_id;
private $temp_path;
protected $upload_dir="_portfolio-items";
public $errors=array();
protected $upload_errors = array(
// http://www.php.net/manual/en/features.file-upload.errors.php
UPLOAD_ERR_OK => "No errors.",
UPLOAD_ERR_INI_SIZE => "Larger than upload_max_filesize.",
UPLOAD_ERR_FORM_SIZE => "Larger than form MAX_FILE_SIZE.",
UPLOAD_ERR_PARTIAL => "Partial upload.",
UPLOAD_ERR_NO_FILE => "No file.",
UPLOAD_ERR_NO_TMP_DIR => "No temporary directory.",
UPLOAD_ERR_CANT_WRITE => "Can't write to disk.",
UPLOAD_ERR_EXTENSION => "File upload stopped by extension."
);
public function attach_file($file){
global $session;
if(!$file || empty($file) || !is_array($file)){
$this->errors[] = 'no file was uploaded';
return false;
}elseif ($file['error'] != 0) {
$this->errors[]=$this->upload_errors[$file['error']];
return false;
}else {
$this->filename = basename($file['name']);
$this->temp_path = $file['tmp_name'];
$this->mimetype = $file['type'];
$this->size = $file['size'];
if(isset($session->message) && $session->message !== ''){
$current_job = Job::find_by_id(intval($session->message));
$this->job_id = $current_job->id;
}
return true;
}
}
defined('DS')?null:define('DS',DIRECTORY_SEPARATOR);
defined('SITE_ROOT')?null:define('SITE_ROOT', DS.'mp_creations');
defined('INC_PATH')?null:define('INC_PATH', SITE_ROOT.DS.'includes');
defined('PUB_PATH')?null:define('PUB_PATH', SITE_ROOT.DS.'public');
public function save(){
if(isset($this->id)){
$this->update();
}else{
if(!empty($this->errors)){
return false;
}
if(empty($this->filename) || empty($this->temp_path)){
$this->errors[] = 'file path not available';
return false;
}
$target_path = PUB_PATH.DS.$this->upload_dir.DS.$this->filename;
if(file_exists($target_path)){
$this->errors[] = "the file {$this->filename} already exists";
return false;
}
if(move_uploaded_file($this->temp_path,$target_path)){
if($this->create()){
unset($this->temp_path);
return true;
}
}else {
$this->errors[]='The file upload failed, possibly due to permission issues';
return false;
}
}
}
The file will be deleted from the temporary directory at the end of the request if it has not been moved away or renamed.
http://php.net/manual/en/features.file-upload.post-method.php
The problem seemed to have been my methods and not anything to do with permissions. I was was using values stored in the session to pass to the move_uploaded_file() function, once I did it directly from the POST request it worked fine. Is it that the move_uploaded_file() needs to be called from a POST request? Anybody care to shed some light on this, please do as I'd love to learn what happening behind the scenes.
Related
I'm developing an api on which it gets an image and resizes it into three sizes and zips it. I have some methods to validate the file, run the resizer class and its methods and finally give files as zip file and a link to download them. Now I have problem with content type validation and zipping. I searched a lot and I couldn't find any tutorial. I'd be thankful if you help me with my errors.
rest.php
<?php
require_once 'constants.php';
abstract class Rest
{
public array $request;
public array $errors = [];
public function __construct()
{
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$this->throwError(REQUEST_METHODS_NOT_VALID, 'Request method is not valid.');
}
$this->request = $_FILES + $_POST;
$fileName = $_FILES['image']['name'];
$fileType = $_FILES['image']['type'];
$this->validateRequest($fileName);
if (empty($this->errors)){
$this->executeApi();
}
$this->response();
}
public abstract function validateRequest($request);
public abstract function executeApi();
public function validateParameters($fieldName, $value, $dataType, $required) {
}
public function throwError($code, $message) {
header("content-type: application/json");
$errorMsg = json_encode(['error'=>['status'=>$code, 'message'=>$message]]);
echo $errorMsg;
exit();
}
public function response() {
//???
}
}
api.php
<?php
require_once 'image-resizer.php';
class Api extends Rest
{
public function validateRequest($request)
{
// if ($request !== 'image/jpeg') {
if ($_SERVER['CONTENT_TYPE'] !== 'image/jpeg') {
$this->throwError(REQUEST_CONTENT_TYPE_NOT_VALID, 'Request content type is not valid.');
$errors = json_encode(array("message" => "Request content type is not valid.", "status" => false));
echo $errors;
}
json_decode($request, true);
}
public function executeApi()
{
$source = $this->request['image'];
$resize = new Resizer();
$resize->imageResizer($source);
}
}
getimagesize is not to be used to validate a file as image
$imgsize = getimagesize($sourceFile);
$srcWidth = $imgsize[0];
$srcHeight = $imgsize[1];
$mime = $imgsize['mime'];
you can use: fileinfo
OR you may validate extension using pathinfo
$allowedExt = ['jpg', 'jpeg', 'png'];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExt)) {
return FALSE;
}
// filesize validation
if (filesize($tmpName) > MAX_FILE_SIZE) {
}
check more on filesize
Edit:
You may check this link for zipping files with PHP
EDIT:
$this->request = $_FILES + $_POST; // this is insecure way to get the data
check $_POST data sanitization
what is a good method to sanitize the whole $_POST array in php?
This is how i upload a file into my database but i am not able to handle my exception when the file uploaded is an invalid format or type.
I am able to handle exception when no file is uploaded but not when the file type is invalid or does not meet the standard.
How do i get this done please?
Controller
public function import($id, Request $request)
{
$country= Country::all()->where('id',$id)->first();
if($request->file('imported-file'))
{
$path = $request->file('imported-file')->getRealPath();
$data = Excel::load($path, function($reader)
{
})->get();
if(!empty($data) && $data->count())
{
foreach ($data->toArray() as $row)
{
if(!empty($row))
{
$dataArray[] =
[
'name' => $row['name'],
];
}
else {
return redirect('admin')->with('error','File format Error');
}
}
if(!empty($dataArray))
{
$country->teams()->createMany($dataArray);
return redirect('admin')->with('status','Countries successfully added');
}
}
}
else {
return redirect('admin')->with('error','No file was uploaded');
}
}
From Laravel's documentation, You can accept only a certain type of file using mime validation rule,
'file' => 'required | mimes:application/vnd.ms-excel',
The mime-type application/vnd.ms-excel will match these file extensions xls xlm xla xlc xlt xlw
I have uploading excel files in one of my project. Hope this will helps you:-
$file = Input::file('imported-file');
Excel::load($file ,function($reader){
$reader->each(function($sheet){
YourMOdelName::firstOrCreate($sheet->toArray());
});
});
YourModelName is your table name suppose if table is users so you have to define User in that case.....
From this way you can get the extenstion of your uploading file:-
$ext= Input::file('imported-file')->getClientOriginalExtension();
echo $ext; //print the extension here
Hope it willl help!
Okay i solved this in a very simple way by checking out the laravel documentation. So here is what i just added
if(($request->file('imported-file')->getClientOriginalExtension() != 'xls, xlm, xla ,xlc, xlt, xlw'))
{
}
else {
//process the file
}
**check_imgupload.class.php**
<?php
class Image extends Connection
{
private $img_name;
private $img_extension;
private $img_size;
private $tmp_name;
private $target_dir;
//getter and setters
public function getadmin_img()
{
$this->img;
}
public function setadmin_img($img='')
{
$this->img=$img;
}
public function getimg_name()
{
$this->img_name;
}
public function setimg_name($imgn='')
{
$this->img_name=$imgn;
}
public function setimg_size($size='')
{
$this->img_size=$size;
}
public function setimg_type($imgty='')
{
$this->img_type=$imgty;
}
public function settmp_img_name($tmpimg='')
{
$this->img_tmp=$tmpimg;
}
public function check_img()
{
if(isset($this->img)){
$errors= array();
//$file_name = $_FILES['image']['name'];
//$file_size =$_FILES['image']['size'];
//$file_tmp =$_FILES['image']['tmp_name'];
//$file_type=$_FILES['image']['type'];
$file_ext=strtolower(end(explode('.',$this->img_name)));
$expensions= array("jpeg","jpg","png","PNG","bmp","Gif");
$target_dir='../Uploads';
if(in_array($file_ext,$expensions)=== false){
$errors[]="extension not allowed, please choose a JPEG or PNG file.";
}
else if($this->img_size> 2097152){
$errors[]='File size must be excately 2 MB';
}
else if(file_exists($target_dir.'/'.$this->img_name))
{
$errors[]='File already exists..';
}
else if(empty($errors)==true){
move_uploaded_file($this->img_tmp,"$target_dir/$this->img_name");
return true;
}
else{
return $errors;
}
}
}
}
**Process_add_user.php**
<?php
session_start();
//load classes
require_once('../classes/db-connection.class.php');
require_once('../classes/user.class.php');
require_once('../classes/locate.class.php');
require_once('../classes/check_img.class.php');
//create an object
$objImage= new Image();
//
//setting the inputs
$admin_img=$_FILES['admin_img'];
$admin_img_name=mysqli_real_escape_string($objImage->conxn,$_FILES['admin_img']['name']);
$size=mysqli_real_escape_string($objImage->conxn,$_FILES['admin_img']['size']);
$type=mysqli_real_escape_string($objImage->conxn,$_FILES['admin_img']['type']);
$tmp_name=mysqli_real_escape_string($objImage->conxn,$_FILES['admin_img']['tmp_name']);
$objImage->setadmin_img($admin_img);
$objImage->setimg_name($admin_img_name);
$objImage->setimg_size($size);
$objImage->setimg_type($type);
$objImage->settmp_img_name($tmp_name);
//check the image extension
$img_return=$objImage->check_img();
//now teh condition for flag
if($img_return==true)
{
$objUser=new User();
$admin_name=mysqli_real_escape_string($objUser->conxn,$_POST['admin_name']);
$admin_email=mysqli_real_escape_string($objUser->conxn,$_POST['admin_email']);
$admin_password=mysqli_real_escape_string($objUser->conxn,$_POST['admin_password']);
$admin_password2=mysqli_real_escape_string($objUser->conxn,$_POST['admin_password2']);
$admin_access_level=mysqli_real_escape_string($objUser->conxn,$_POST['admin_access_level']);
$objUser->setAdmin_username($admin_name);
$objUser->setPassword($admin_password);
$objUser->setAdmin_email($admin_email);
$objUser->setaccess_level($admin_access_level);
$flag=$objUser->addadmin();
}
elseif($img_return==$errors)
echo $img_return;
//Errorrs are not shown
//new locate('../index.php?error='.base64_encode());
else
new locate('../../index');
I Have checked for image before upload when the check_img()function return true image is uploaded and its all right and when the $errors is returned i want to show the same error returned as $errors.
echo $errors is not working.
To show an array you can var_dump() or print_r()
Try this...
if(isset($this->img)){
...any of this stuff...
}
else{
return $errors;
print_r($errors);
}
}
}
That should do it.
NOTE: I strongly advise against this for error handling. The output to the page is ugly and just not a user friendly or graceful way to handle errors.
I am developing a file uploaded class, and trying to perform few validation before other codes, but its returning all vars instead of false, check following code....
class FileUploader
{
private $filePath;
function __construct($file_path) {
if(file_exists($file_path)) {
$this->filePath = $file_path;
}
else return false;
}
}
When I am using this class like following....
$file_path = getcwd().'\img.pn'; //invalid path
$file_uploader = new FileUploader($file_path);
if($file_uploader) {
//process
}
else {
echo 'Invalid File Path!';
}
But it doesn't echo Invalid File Path as expected, when i tried var_dump, it returned following output...
object(FileUploader)[1]
private 'filePath' => null
Please help to fix this. thanks.
You might consider using an exception in the constructor as constructors should no return anything. (Have a look at this question).
Otherwise you may create a function to check the file_path :
class FileUploader
{
private $filePath;
function __construct($file_path) {
$this->filePath = $file_path;
}
function isValidFilePath() {
return file_exists($this->file_path);
}
}
and then :
$file_path = getcwd().'\img.pn'; //invalid path
$file_uploader = new FileUploader($file_path);
if($file_uploader->isValidFilePath()) {
//process
}
else {
echo 'Invalid File Path!';
}
If a user uploads a file and the contents are retrieved like so
$file = $_FILES['uploadedFile'];
Then, the file is sent to a function to make sure it's an accepted file type. If it is, save it on the server
function saveInputFile($file){
if($check->checkFile($file)== TRUE){
//save $file on my server
}
else{
echo "can't be saved!";
}
}
Assuming it passes the checkFile function, how can I then save this file to my server from within the saveInputFile function? Can I set the file equal to a variable, and then save that variable or do I have to save the file directly from the POST data?
I've seen it done like this, but I already have the file passed into this function.
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['uploadedfile']['name']). " has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
When it comes down to it, I want to save a file in the following function. Can I pass the file like a variable as I did in the saveInputFile function above, or does it not work like this?
You can make the upload file a type of it's own that has the methods it needs next to it's data. That will make the usage more flexible:
$upload = new UploadFile($_FILES['uploadedFile']);
$message = saveInputFile($upload);
echo $message;
function saveInputFile(UploadFile $upload)
{
if ($check->checkFile($upload->getBasename()) == TRUE) {
$message = $upload->moveTo($target_path)
? sprintf('The file %s has been uploaded', $upload->getBasename())
: 'There was an error uploading the file, please try again!'
;
} else {
$message = "can't be saved!";
}
return $message;
}
The new type UploadFile represents one file from the the $_FILE array, it is a class that wraps the basic data and methods a file-upload carries. Here is some example code:
class UploadFile
{
protected $file;
private $filename;
public function __construct(array $file)
{
$this->file = $file;
}
public function hasError()
{
return $this->getProperty('error') !== UPLOAD_ERR_OK;
}
public function getError()
{
return $this->getProperty('error');
}
public function getBasename()
{
return basename($this->getProperty('name'));
}
public function getFilename()
{
return $this->filename;
}
/**
* #param $newName
* #return NULL|SplFileInfo
* #throws BadMethodCallException
*/
public function moveTo($newName)
{
$newName = (string)$newName;
$filename = $this->getFilename();
if ($filename !== NULL) {
throw new BadMethodCallException(sprintf('Upload file (%s) has been already moved (%s).', $this->getBasename(), $filename));
}
$tmpName = $this->getProperty('tmp_name');
if (move_uploaded_file($tmpName, $newName)) {
$this->filename = realpath($newName);
}
return $this->getFileInfo();
}
/**
* #return SplFileInfo|NULL
*/
public function getFileInfo()
{
$filename = $this->getFilename();
if ($filename !== NULL) {
return new SplFileInfo($filename);
}
}
protected function getProperty($name, $default = NULL)
{
if (isset($this->file[$name])) {
return $this->file[$name];
}
return $default;
}
}
Use it at your will. See as well SplFileInfo and the documentation about file uploads in the PHP manual which documents the structure of the $_FILE array and the PHP upload error codes (which are important).
Your move_uploaded_file function should take 2 parameters, the source file name and the destination file name.
In PHP the file move function is called rename.