How to overcome getClientOriginalName() error in Laravel dropzone file upload? - php

I am using Laravel 5.0, for image uploading I am using dropzone.js. Actually file uploading to folder and database but it is throwing error like
Call to a member function getClientOriginalName() on a non-object
on post method.
Where have I gone wrong?
View File,
<form method="POST" class="dropzone dz-clickable" id="productDropzone" action="{{url()}}/cms/website/pages/upload_files" enctype="multipart/form-data">
<div class="dz-default dz-message">
<span>Drop files here to upload</span>
</div>
<input name="_token" type="hidden" value="{{ csrf_token() }}">
<input type="submit" value="Upload" id="submit_all"/>
</form>
Below is my js,
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("form#productDropzone", {
paramName : 'file',
maxFilesize: 3, // MB
maxFiles: 3,
autoProcessQueue: false,
addRemoveLinks: true,
init: function() {
this.on("addedfile", function(file) { fileupload_flag = 1; });
this.on("complete", function(file) { fileupload_flag = 0; });
},
accept: function(file, done)
{
var re = /(?:\.([^.]+))?$/;
var ext = re.exec(file.name)[1];
ext = ext.toUpperCase();
if ( ext == "JPG" || ext == "JPEG" || ext == "PNG" || ext == "GIF" || ext == "BMP")
{
done();
}else {
done("Please select only supported picture files.");
}
},
success: function( file, response ) {
obj = JSON.parse(response);
file.previewElement.querySelector("file").src = obj.src;
// alert(obj.src);return false;
}
});
$('#submit_all').click(function(){
myDropzone.processQueue();
});
Controller function,
$com_id = Auth::user()->company_id;
$file = Request::file('file');
$destinationPath = public_path() . '/images/section/';
$filename = strtolower($file->getClientOriginalName());
$upload_success = $file->move($destinationPath, $filename);
if ($upload_success) {
$upload = new Cms_banner_master();
$upload->product_banner = json_encode($filename);
$upload->company_id = $com_id;
$upload->home_banner ="1";
$upload->save();
return Response::json(array($fileName));
} else
{
return Response::json('error', 400);
}

If you want to prevent the error from happening, you can add some validity checks on the file first.
For example with the isValid method
Update: I added the hasFile method too.
if(Request::hasFile('file') {
$file = Request::file('file');
if($file->isValid()) {
$destinationPath = public_path() . '/images/section/';
$filename = strtolower($file->getClientOriginalName());
$upload_success = $file->move($destinationPath, $filename);
if ($upload_success) {
...
}
}
} else {
return Response::json('No file uploaded', 409);
}
And I would also generate a new name for the uploaded file, this way you don't need the getClientOriginalName:
$filename = $com_id.'_'.date('YmdHis')'.'.$file->guessExtension();
In the spirit of "never trust the users" and not letting them 'choose' a file name from a file that you will be saving on your server.

Related

Having problem with uploading multiple files in one request using dropzone

Am trying to update user image database column using dropzone plugin in one request but when i set uploadMultiple to true is not working no image move to folder neither database. But when i set it to false only last image name move to user image column but all images move to folder.
Thanks in advance
Here is my code
Dropzone.options.mydropzone =
{
autoProcessQueue: false,
addRemoveLinks: true,
dictMaxFilesExceeded: "Maximum upload limit reached",
dictInvalidFileType: "upload only JPG/PNG/JPEG/GIF/BMP",
acceptedFiles: '.png,.jpg,.jpeg,.gif,.bmp',
parallelUploads: 10,
// uploadMultiple: true,
init: function ()
{
var submitButton = document.querySelector('#letupload');
myDropzone = this;
submitButton.addEventListener("click", function(){
myDropzone.processQueue();
});
this.on("complete", function(){
if (this.getQueuedFiles().length == 0 && this.getUploadingFiles().length == 0)
{
var _this = this;
_this.removeAllFiles();
}
//console.log(this.getUploadingFiles());
});
},
};
Server Side
if (!empty($_FILES)) {
$temp_file = $_FILES['file']['tmp_name'];
$targetDir = '../../user_images/';
$filename = rand().$_FILES['file']['name'];
$targetFile = $targetDir.$filename;
if (move_uploaded_file($temp_file, $targetFile)) {
$sql="UPDATE img SET Image='$filename' WHERE User_id = '$memberid' ";//
if(!$qsql=mysqli_query($con,$sql))
{
echo mysqli_error($con);
}
}
}
After follow Mohammed link every images to to destination folder but only last image save into that database Below is my new server side code
if (!empty($_FILES)) {
foreach($_FILES['file']['tmp_name'] as $key => $value) {
$temp_file = $_FILES['file']['tmp_name'][$key];
$targetDir = '../../user_images/';
$filename = rand().$_FILES['file']['name'][$key];
$targetFile = $targetDir.$filename;
if (move_uploaded_file($temp_file,$targetFile)) {
$sql="UPDATE img SET Image='$filename' WHERE User_id = '$memberid' ";//
if(!$qsql=mysqli_query($con,$sql))
{
echo mysqli_error($con);
}
}
}
}
You are updating at each iteration , so the value at the end of script will be the name of the last image uploaded , so there is a way to solve this issue trying this snippet of code :
Insert into an array (i nammed id $images) the file name of uploaded
files.
convert array into spring separated by comma , using implode
function .(i used the same variable $images).
update the row with images name .
Code example :
if (!empty($_FILES)) {
$images=array[];
foreach($_FILES['file']['tmp_name'] as $key => $value) {
$temp_file = $_FILES['file']['tmp_name'][$key];
$targetDir = '../../user_images/';
$filename = rand().$_FILES['file']['name'][$key];
$targetFile = $targetDir.$filename;
if (move_uploaded_file($temp_file,$targetFile)) {
$images[]= $filename;
}
}
$images = implode(',',$images);
$sql="UPDATE img SET Image='$images' WHERE User_id = '$memberid' ";//
if(!$qsql=mysqli_query($con,$sql)){
echo mysqli_error($con);
}
}
Hope this help you .
Thanks to #Mohammed after I try your code, the problem of saving images name into database still persist, I now discover that you declare empty array inside the foreach so below is the working code
Dropzone Js
Dropzone.options.mydropzone =
{
autoProcessQueue: false,
addRemoveLinks: true,
dictMaxFilesExceeded: "Maximum upload limit reached",
dictInvalidFileType: "upload only JPG/PNG/JPEG/GIF/BMP",
acceptedFiles: '.png,.jpg,.jpeg,.gif,.bmp',
parallelUploads: 10,
uploadMultiple: true,
init: function ()
{
var submitButton = document.querySelector('#letupload');
myDropzone = this;
submitButton.addEventListener("click", function(){
myDropzone.processQueue();
});
this.on("complete", function(file, response){
if (this.getQueuedFiles().length == 0 && this.getUploadingFiles().length == 0)
{
var _this = this;
_this.removeAllFiles();
}
console.log(this.getUploadingFiles());
});
},
};
Server Side
if (!empty($_FILES)) {
$empty_img_arr=array();
foreach($_FILES['file']['tmp_name'] as $key => $value) {
$temp_file = $_FILES['file']['tmp_name'][$key];
$targetDir = '../../user_images/';
$filename = rand().$_FILES['file']['name'][$key];
$targetFile = $targetDir.$filename;
if (move_uploaded_file($temp_file,$targetFile)) {
$empty_img_arr[]= $filename;
$image = implode(',',$empty_img_arr);
$sql="UPDATE img SET Image='$image' WHERE User_id = '$memberid' ";//
if(!$qsql=mysqli_query($con,$sql))
{
echo mysqli_error($con);
}
}
}
}
Thanks so much really appreciate

How to retrieve FormData in Laravel

I am sending formdata from Angular 2 to Laravel API to save the recorded voice from RecordRTC js. Checked the filename, filetype and blob file on console. it is showing. but not able to retrieve on Laravel backend code.
public uploadToServer() {
let blob = this.recordRTC instanceof Blob ? this.recordRTC : this.recordRTC.blob;
let fileType = blob.type.split('/')[0] || 'audio';
let fileName = (Math.random() * 1000).toString().replace('.', '');
if (fileType === 'audio') {
fileName += '.' + (!!navigator.mozGetUserMedia ? 'ogg' : 'wav');
} else {
fileName += '.webm';
}
// create FormData
var formData: FormData = new FormData();
console.log(fileName);
console.log(blob);
console.log(fileType);
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
console.log(formData);
this.recordingService.saveRecording(formData).subscribe(
data => this.saveRecordingSuccess(data),
error => this.saveRecordingFail(error)
);
}
Laravel Code:-
public function saveRecording(Request $request)
{
$fileName = '';
$tempName = '';
$file_idx = '';
if (!empty($_FILES['audio-blob'])) {
$file_idx = 'audio-blob';
$fileName = $_POST['audio-filename'];
$tempName = $_FILES[$file_idx]['tmp_name'];
}
if (empty($fileName) || empty($tempName)) {
if(empty($tempName)) {
echo 'Invalid temp_name: '.$tempName;
return;
}
echo 'Invalid file name: '.$fileName;
return;
}
$filePath = public_path('voiceRecording/' . $fileName);
// make sure that one can upload only allowed audio/video files
$allowed = array(
'webm',
'wav'
);
$extension = pathinfo($filePath, PATHINFO_EXTENSION);
if (!$extension || empty($extension) || !in_array($extension, $allowed)) {
echo 'Invalid file extension: '.$extension;
return;
}
if (!move_uploaded_file($tempName, $filePath)) {
// error code
return;
}
}
In laravel code I have not receiving any files and post data.
You have to put on your form the mime type, like in JQuery Ajax, have the property
mimeType: "multipart/form-data"

How to return File Path in Html of Gulp s3 Upload?

I'm creating an image optimiser using gulp and PHP for the Upload.
I want to be able to output the file path url of the uploaded file into index.php what is the best way to do it..
i've tried mimicking the output of the file path using the below, but didn't work..
-: print 'https://footpatrol.s3.amazonaws.com/images/'.date('Y').'/'. date('d-m').'/'.$newfilename.'';
PHP Code.
<?php
$files = glob('images/*'); // get all file names
foreach($files as $file){ // iterate files
if(is_file($file))
unlink($file); // delete file
}
foreach($_FILES['file']['name'] as $index=>$name){
$filename = $name;
if(!file_exists("images/".$filename)){
$file_basename = substr($filename, 0, strripos($filename, '.')); // get file extention
$file_ext = substr($filename, strripos($filename, '.')); // get file name
$newfilename = md5($file_basename) . $file_ext;
move_uploaded_file($_FILES["file"]["tmp_name"][$index],"images/" . $newfilename);
if( move_uploaded_file($_FILES["file"]["tmp_name"][$index],"images/" . $newfilename)){
print '<div class="img">https://footpatrol.s3.amazonaws.com/images/'.date('Y').'/'. date('d-m').'/'.$newfilename.'</div>';
}
}
}
?>
Gulp Code..
var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
var clean = require('gulp-clean');
var s3 = require('gulp-s3');
var AWS = require('aws-sdk');
var fs = require('fs')
var pngquant = require('imagemin-pngquant');
var jpegrecompress = require('imagemin-jpeg-recompress');
var moment = require('moment');
var runSequence = require('run-sequence');
// Delete files in image folder
gulp.task('cleanTemp', function(cb) {
return gulp.src('dist/images/*', { read: false }).pipe(clean());
cb(err)
});
// Delete files in image folder
gulp.task('delete', ['image'], function() {
return gulp.src('./images/*', { read: false })
.pipe(clean());
});
var year = moment().format('YYYY');
var today = moment().format('MM-DD');
// // Image Optimisation
//console.log('dist/images/'+year+'/'+today)
gulp.task('image',['cleanTemp'], function() {
return gulp.src('images/*')
.pipe(imagemin([
imagemin.gifsicle({ interlaced: true }),
jpegrecompress({
progressive: true,
max: 70,
min: 55
}),
pngquant({ quality: '70-80' })
]))
.pipe(gulp.dest('dist/images/' + year + '/' + today + ''));
});
aws = JSON.parse(fs.readFileSync('./aws.json'));
// // UPLOAD
gulp.task('upload', function() {
return gulp.src('./dist/**')
.pipe(s3(aws))
});
// Watch Image files
gulp.task('watch', function() {
gulp.watch('images/*', function(event) {
runSequence('cleanTemp', ['image','upload']);
});
});
// Default Task
gulp.task('default', ['cleanTemp','image', 'upload']);

add files in to webroot/files

I have a problem, I have view file, but how to save these uploads in to webroot/files. Im using CakePHP:
This is my uploadfile.ctp
echo $this->Form->create('YourModel', array('type' => 'file','enctype'=>'multipart/form-data'));
echo $this->Form->input('files.', array('type' => 'file', 'multiple'));
echo $this->Form->end('Submit');
I dont know where to start in Controller, I really need these files in to webroot/files, thankyou !
At the moment I have in Controller:
public function uploadFile() {
if ($this->request->is('UploadFile')) {
$tmp_name=$this->request->data['UploadFile']['image'];
$filename = time().$this->request->data['UploadFile']['image']['name'];
if (move_uploaded_file($tmp_name['tmp_name'],WWW_ROOT."/files".$filename)) {
} else {
$this->Session->setFlash('There was a problem uploading file. Please try again.','default',array('class'=>'alert alert-danger'));
}
}
}
UPDATE
Now I have updated view file and updated Controller, where I want to upload multiple files, but only one file going in to files folder.
View file:
<?php
echo $this->Form->create('uploadFile', array( 'type' => 'file'));
?>
<div class="input_fields_wrap">
<label for="uploadFilefiles"></label>
<input type="file" name="data[files]" id="uploadFilefiles">
</div>
<button type="button" class="add_field_button">+</button> <br><br>
<form name="frm1" method="post" onsubmit="return greeting()">
<input type="submit" value="Submit">
</form>
<?php
echo $this->Html->script('addFile');
Controller File:
public function uploadFile() {
$filename = '';
if ($this->request->is('post')) { // checks for the post values
$uploadData = $this->data['files'];
print_r($this->data['files']); die;
if ( $uploadData['size'] == 0 || $uploadData['error'] !== 0) { // checks for the errors and size of the uploaded file
echo "Failide maht kokku ei tohi olla üle 5MB";
return false;
}
$filename = basename($uploadData['name']); // gets the base name of the uploaded file
$uploadFolder = WWW_ROOT. 'files'; // path where the uploaded file has to be saved
$filename = $filename; // adding time stamp for the uploaded image for uniqueness
$uploadPath = $uploadFolder . DS . $filename;
if( !file_exists($uploadFolder) ){
mkdir($uploadFolder); // creates folder if not found
}
if (!move_uploaded_file($uploadData['tmp_name'], $uploadPath)) {
return false;
}
echo "Sa sisestasid faili(d): $filename";
}
}
and this Javascript:
$(document).ready(function() {
var max_fields = 3;
var wrapper = $(".input_fields_wrap");
var add_button = $(".add_field_button");
var x = 1;
$(add_button).click(function(e){
e.preventDefault();
if(x < max_fields){
x++;
$(wrapper).append("<div><input type='file' name='data[files]' id='uploadFilefiles'/><a href='#' class='remove_field'>Kustuta</a></div>");
}
});
$(wrapper).on("click",".remove_field", function(e){ //user click on remove text
e.preventDefault(); $(this).parent('div').remove(); x--;
})
});
How I can upload all 3 files in to webroot/files folder ?
try this code , this is a demo code and its is work on my server
<div class="col-sm-12">
<?php echo $this->Form->file('Feature.image.',array('class'=>'form-control','label'=>false,'div'=>false,'required','multiple'));?>
</div>
if ($this->request->is('post')) {
$data=$this->request->data['Feature']['image'];
foreach ($data as $key => $value) {
$this->request->data['Feature']['image'][$key]['name'];
$tmp_name=$this->request->data['Feature']['image'][$key];
$filename = time().$this->request->data['Feature']['image'][$key]['name'];
if (move_uploaded_file($tmp_name['tmp_name'],WWW_ROOT."/img/feature/".$filename)) {
$updatefile= $this->Feature->updateAll(
array('Feature.image' => "'$filename'"),
array('Feature.id' => $id,'Feature.userid'=>$this->Session->read('Auth.User.id'))
);
if($updatefile==1){
$file = new File(WWW_ROOT . 'img/feature/'.$featuredata['Feature']['image'], false, 0777);
if($file->delete()) {
$this->Session->setFlash('File uploaded successfuly uploaded.','default',array('class'=>'alert alert-success'),'success');
return $this->redirect(array('controller'=>'Users','action'=>'featureshow')) ;
}
}
} else {
$this->Session->setFlash('There was a problem uploading file. Please try again.','default',array('class'=>'alert alert-danger'));
}
}
}
No, of course you do not need a table.
I guess you are looking for something like this in your controller:
foreach($this->request->data['files'] as $file){
move_uploaded_file($file['tmp_name'], WWW_ROOT . 'uploads/' . $uuid . '.jpg');
}
Use this:-
$uploadedFile = $this->request->params['form']['uploadCsv']['tmp_name'];
$dir = WWW_ROOT . 'files/';
if ( !is_dir( $dir ) ) {
mkdir($dir);
chmod( $dir , 777);
}
$fileName = 'file_' . date( 'Y_m_d_h_i_s', time() );
move_uploaded_file( $uploadedFile, $dir. $fileName . '.csv' );
This is a sample code which works on my server, and should work for you as well

Form not sending files other than images

I'm trying to upload files using php and I am copying and renaming files from other instances that are actually working (uploading pics). But for some reason the form is not passing (POST) any file that is NOT an image :-/
So, in resume, I am getting this (Google) 'request payload' for an image file:
------WebKitFormBoundaryrHOYostaC2KnUDlD
Content-Disposition: form-data; name="uploaded_file[]"; filename="image.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryrHOYostaC2KnUDlD--
But this for txt or pdf files:
------WebKitFormBoundaryc1RJOtSOpYKAZiBz--
Here is the form and script (functions are to avoid the user to click 'Submit', those work good):
echo '
<script language="JavaScript" type="text/javascript">
function HandleBrowseClick()
{
var fileinput = document.getElementById("uploaded_file");
fileinput.click();
}
function Handlechange()
{
var fileinput = document.getElementById("uploaded_file");
var textinput = document.getElementById("filename");
textinput.value = fileinput.value;
}
</script>';
echo '
<form enctype="multipart/form-data" target="_blank" name="send_file" id="send_file" method="post" action="file_upload.php">
<input type="file" class="hide button" id="uploaded_file" name="uploaded_file" onChange="Handlechange();"/>
<button type="submit" id="btn">Upload!</button>
</form>';
echo '
<div onclick="HandleBrowseClick();" id="fakeBrowse" >Load a file</div>
<input type="text" id="filename" size="50" readonly="true" />
';
So, since it's not passing anything, in my file_upload.php I get the "ERROR: Please browse for a file before clicking the upload button." or "Invalid argument supplied for foreach()" (if I expect an array) error.
I tried using application/x-www-form-urlencoded allowing the same result. Now for those who get mad if there is no question marks: Why the form works fine with images but not so with other kind of files? What am I dong wrong?
Here is the first few lines of file_upload.php (I don't think it's necessary but you never know):
$target = "../files/temp/";
foreach ($_FILES["uploaded_file"]["error"] as $key => $error) {
if ($error != UPLOAD_ERR_OK) { echo "error"; die;}
$fileName = $target . $_FILES["uploaded_file"]["name"][$key]; // The file name
$fileTmpLoc = $_FILES["uploaded_file"]["tmp_name"][$key]; // File in the PHP tmp folder
$fileType = $_FILES["uploaded_file"]["type"][$key]; // The type of file it is
$fileSize = $_FILES["uploaded_file"]["size"][$key]; // File size in bytes
$fileErrorMsg = $_FILES["uploaded_file"]["error"][$key]; // 0 for false... and 1 for true last $key!!!
$fileName = preg_replace('#[^a-z.0-9]#i', '', $fileName); // filter the $filename
$fileName = strtolower($fileName);
$kaboom = explode(".", $fileName); // Split file name into an array using the dot
$fileExt = end($kaboom); // Now target the last array element to get the file extension
if (!$fileTmpLoc) { // if file not chosen
echo "ERROR: Please browse for a file before clicking the upload button.";
exit();
}
else if ($fileErrorMsg == 1) { // if file upload error key is equal to 1
echo "ERROR: An error occurred while processing the file. Try again.";
exit();
}
Finally, some more js:
if (window.FormData) {
formdata = new FormData();
document.getElementById("btn").style.display = "none";
}
input.addEventListener("change", function (evt) {
document.getElementById("response").innerHTML = "Loading . . ."
var i = 0, len = this.files.length, img, reader, file;
for ( ; i < len; i++ ) {
file = this.files[i];
if (!!file.type.match(/image.*/)) {
if (formdata) {
formdata.append("uploaded_file[]", file);
}
}
}
if (formdata) {
$.ajax({
url: "file_upload.php",
type: "POST",
data: formdata,
processData: false,
contentType: false
}).done(function (res) {
document.getElementById("response").innerHTML = res;
if ( window.FileReader ) {
reader = new FileReader();
reader.onloadend = function (e) {
showUploadedItem(e.target.result, file.fileName);
};
reader.readAsDataURL(file);
}
});
}
}, false);
where changing contentType doesn't make any diference
THANKS!!!
You have to define the MIME types for your files. For example
.pdf application/pdf
.doc application/msword
Okay, my bad. The js file has an image filter. It started working right away after I removed it.

Categories