Problems with uploading file using Vue.js and Laravel - php

Vue template (File upload): This input field is generated from another module, Where the from generated by drag and drop input field.
<input type="file" #change="uploadFile(data,$event)" class="custom-file-input" id="validatedCustomFile">
Script Vuejs:
data () {
return {
//baseform
baseForm: new Form({
form:this.data ? JSON.parse(this.data.dataForm) : '',
}),
}
},
methods: {
uploadFile(data,e){
let file = e.target.files[0];
data.value = file;
},
// form data submit
formSubmit() {
const config = {
headers: {'Content-Type': 'multipart/form-data'}
}
let formData = new FormData();
formData.append('form',JSON.stringify(this.baseForm.form));
axios.post('/api/order-data',formData, config)
.then((order)=>{
//
}).catch(()=>{
//
})
}
}
Controller: Here is the controller code
$formData = json_decode($request->form, true);
foreach ($formData as $key) {
if($key['field'] == 'fileUpload') {
dd($key['value']);
}
}
I am getting empty value after die dump $key['value']

Related

empty file when upload a mediaObject

When I try to upload a file on my Symfony API, I have an error from MediaObjectAction.php which is a controller.
This file looks like this :
final class CreateMediaObjectAction extends AbstractController
{
public function __invoke(Request $request): MediaObject
{
$uploadedFile = $request->files->get('file');
if (!$uploadedFile) {
throw new BadRequestHttpException('"file" is required');
}
$mediaObject = new MediaObject();
$mediaObject->file = $uploadedFile;
return $mediaObject;
}
}
and it throws me the error : "file" is required
In the front-end, I use ReactJS and I do a simple file upload with these functions :
const handleFileChange = (event) => {
console.log(event.target.files[0])
setFile({ selectedFile: event.target.files[0], loaded: 0 })
}
const uploadFile = () => {
FileUtils.uploadFile(MEDIA_OBJECT_ENDPOINT, file.selectedFile)
.then((response) => {
console.log(response)
})
const FileUtils = {
uploadFile: async (url, file) => {
const data = new FormData()
data.append('name', 'file')
data.append('file', file)
const response = await api.post(url, data)
return response
},
}
And in html, the file input looks like this :
<input
type="file"
id="file"
name="file"
onChange={handleFileChange}
></input>
As you can see, it is very basic, but it does not work and I cannot figure out why. Do you have an idea of what I miss ?
PS : The function api.post() works very well, the problem does not come from it.

How to send a file via Axios to Laravel

I need to post a File from client to server via Axios.
Here is my Vuejs code :
methods: {
'successUpload': function (file) {
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
axios.post('/Upload/File',file, config).then(function (response) {
console.log(response.data);
});
}
}
And here is my Laravel code for handling sent file :
public function uploadFile(Request $request)
{
if($request->hasFile('file'))
return "It's a File";
return "No! It's not a File";
}
But it always returns No It's not a File.
Any helps would be great appreciated.
You have to create a FormData object and append the image file.
methods: {
'successUpload': function (file) {
let data = new FormData();
data.append('file', document.getElementById('file').files[0]);
axios.post('/Upload/File',data).then(function (response) {
console.log(response.data);
});
}
}
An example is here.
Let me know if that works.

Angular/PHP: upload file data in $_POST, not $_FILES

I'm using AngularJS v1.6.1, Apache 2.4.10 on Debian with PHP 5.6.24 and I'm trying to upload a file to my server using $http POST service.
On my php.ini, max file size is set to 8Mo, max post size too, upload file is on, and memory size limit is set to 128Mo.
Form:
<input type="file" accept="application/pdf" id="uploadOT" max-files="1" ng-model="uploadOT" name="uploadOT" valid-file required ng-class="{'md-input-invalid':uploadForm.uploadOT.$error.validFile}" />
Angular directive: (when input content change, get a FileReader object and send file)
myModule.directive('validFile', function() {
return {
require: 'ngModel',
link: function(scope, elt, attrs, ctrl) {
ctrl.$setValidity('validFile', elt.val() !== '');
elt.bind('change', function() {
var file = document.getElementById('uploadOT').files;
var reader = new FileReader();
reader.onload = function(e) {
scope.sendFile(reader, scope.id);
};
scope.showUploadProgress = true;
scope.filename = file[0].name;
reader.readAsBinaryString(file[0]);
ctrl.$setValidity('validFile', elt.val() !== '');
scope.$apply(function() {
ctrl.$setViewValue(elt.val());
ctrl.$render();
});
});
}
};
});
Inside controller:
$scope.sendFile = function(reader, id) {
var fd = new FormData();
fd.append('id', id);
fd.append('file', reader.result);
fd.append('MAX_FILE_SIZE', 8 * 1024 * 1024);
$http.post('api/upload.php', fd, {
headers: {'Content-Type' : undefined },
transformRequest: angular.identity
}).then(function() {
alert('upload success');
}, function() {
$scope.showUploadError = true;
$scope.showUploadProgress = false;
$scope.postError = 'Une erreur inconnue est survenue !';
});
};
On server side (file api/upload.php), I print variables $_POST and $_FILES with print_r().
Why is $_FILES always empty, and my file data is in $_POST['file']?
I can create file from $_POST['file'] data with php function file_put_contents() but I cannot make verifications that I can make with $_FILES. Is it really important (security issues)?
If I change my POST Content-Type to multipart/form-data, the same thing happend.
I presume it's because you forgot to specify the encoding type of your form element.
enctype="multipart/form-data"
So, by default - the browser will assume that the form encoding type is "application/x-www-form-urlencoded" which does not support files in this way. You can still securely send file binary data with the stock encoding method however, this might be where performance and functionality are determining factors to which you choose. I recommend running some tests to confirm which is the fastest. In some cases, the difference will be negligible and will likely be for sake of consistency.
Skip the FileReader API and use the file object directly:
<input type=file files-input ng-model="files" ng-change="upload()" />
The filesInput Directive
angular.module("myApp").directive("filesInput", function() {
return {
require: 'ngModel',
link: function linkFn (scope, elem, attrs, ngModel) {
elem.on("change", function (e) {
ngModel.$setViewValue(elem[0].files, "change");
});
},
};
});
The upload() function
vm.upload = function() {
//var formData = new $window.FormData();
//formData.append("file-0", vm.files[0]);
var config = { headers: { "Content-Type": undefined } };
$http.post(url, vm.files[0], config)
.then(function(response) {
vm.result = "SUCCESS";
}).catch(function(response) {
vm.result = "ERROR "+response.status;
});
};
The XHR API send() method can post either a file object or a FormData object. It is more efficient to send the file object directly as the XHR API uses base64 encoding for the FormData object which has a 33% overhead.
The DEMO on PLNKR.
To make it works, I had to do these modifications:
Directive:
myModule.directive('validFile', function() {
return {
require: 'ngModel',
link: function(scope, elt, attrs, ctrl) {
ctrl.$setValidity('validFile', elt.val() !== '');
elt.bind('change', function() {
var file = document.getElementById('uploadOT').files;
var reader = new FileReader();
reader.onload = function(e) {
scope.sendFile(file[0], scope.OT); ////CHANGE HERE
};
scope.showUploadProgress = true;
scope.filename = file[0].name;
reader.readAsArrayBuffer(file[0]); ////CHANGE HERE
ctrl.$setValidity('validFile', elt.val() !== '');
scope.$apply(function() {
ctrl.$setViewValue(elt.val());
ctrl.$render();
});
});
}
};
});
Inside Controller
$scope.sendFile = function(file, id) {
var fd = new FormData();
fd.append('id', id);
fd.append('file', file);
fd.append('MAX_FILE_SIZE', 8 * 1024 * 1024);
$http({
method: 'POST',
url: 'upload.php',
data: fd,
headers: {'Content-Type': undefined, 'Process-Data': false},
transformRequest: angular.identity
}).then( function() {
console.log('success');
}, function() {
console.log('failure');
});
};

How to upload a CSV file using AJAX with custom prefilter in laravel 4.2

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]);
}

Get File Input Value in Laravel Via AngularJS form

I want to get value from file input from angularjs form in laravel, but i can't get the value.
why?
angularjs:
<div ng-controller="UploadImgController" >
<div ng-repeat="image in images">
<img ng-src="{{image.image}}" />
</div>
<form ng-submit="uploadImg()" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="path" id="path" ng-model="addimages.path" accept="image/*" app-filereader>
<input type="text" name="propertyid" ng-model="addimages.propertyid">
<input type="submit" value="Upload Image" name="submit" class="btn btn-primary" >
</form>
</div>
laravel (UploadImgController.php):
public function store()
{
$file = Input::file('path');
echo "file: ".$file;
}
(routes.php):
Route::resource('img','UploadImgController');
I got no value. What should I do? Thank you. :)
I recommend using ng-file-upload.
View
<button ng-file-select ng-model="myFiles" ng-file-change="upload($files)">Upload</button>
Angular JS
var app = angular.module('fileUpload', ['angularFileUpload']);
app.controller('MyCtrl', ['$scope', '$upload', function ($scope, $upload) {
$scope.upload = function (files) {
if (files && files.length){
for (var i = files.length - 1; i >= 0; i--) {
var file = files[i];
$upload.upload({
url: '/upload',
fields: {key: 'value'},
file: file
})
.progress(function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('File upload ' + progressPercentage + "% complete.");
})
.success(function (data, status, headers, config) {
console.log(data);
})
.error(function(data, status, headers, config) {
console.log(data);
});
}
}
};
}
]);
Laravel Route
Route::post('upload', [
'uses' => 'FileUploadController#upload'
]);
Laravel Controller
public function upload() {
$file = \Input::file('file');
return $file;
}
You can pull that off without a plugin actually. I did face a similar problem once and this is how I went about it.
View
<input type="file" name="file" onchange="angular.element(this).scope().uploadImage(this.files)"/>
Angularjs Controller
$scope.uploadavtar = function (files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
$http.post("/upload-url" + $scope.school.profile.id, fd, {
withCredentials: true,
headers: {'Content-Type': undefined},
transformRequest: angular.identity
}).then(function successCallback(response) {
$scope.result = response;
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
console.log(response);
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
Routes.php
Route::post('/upload-url', 'UsersController#uploadFile');
Laravel Controller
// Upload files
public function uploadFile(Requests\UpdateuploadfileRequest $request, $id)
{
$extension = Input::file('file')->getClientOriginalExtension();
$fileName = time().'.'.$extension; // renameing image
$destination = 'uploads/img'. $fileName;
move_uploaded_file($_FILES['file']['tmp_name'], $destination);
}
}
Request validation file (UpdateuploadfileRequest.php)
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [
];
return $rules;
}

Categories