I'm working on a Laravel Spark project and I am trying to get a form to upload a folder to my S3 bucket. I have the form built:
<form enctype="multipart/form-data">
<input type="file" name="resume" v-model="form.resume">
<button #click="updateProfile">Update Profile</button>
</form>
Then I have a vue component set up to handle the form submit:
Vue.component('resume-links', {
template: '#edit-resume-links',
data() {
return {
form: new SparkForm({
resume: ''
})
};
},
methods: {
updateProfile() {
console.log(this.form.resume);
Spark.post('/route/to/controller', this.form).then(response => {
console.log(response);
});
}
}
});
Then in my laravel controller:
$resume = $request->file('resume');
$resumeFileName = time() . '.' . $resume->getClientOriginalExtension();
$s3 = \Storage::disk('s3');
$filePath = '/resumes/' . $resumeFileName;
$s3->put($filePath, file_get_contents($resume), 'public');
When I try to submit the form with a file it throws this error:
Call to a member function getClientOriginalExtension() on null
I have tried var_dumping $resume right after setting it to the file() and what I see outputted to the console is a bunch of js looking code
From everything that I reading it looks like file uploads with Laravel is super easy and I don't know why I am having this issue. Any assistance/advice would be appreciated! Thanks!
First of all, your file input needs to have the v-el attribute rather than v-model.
In your case it would be <input type="file" name="form" v-el:resume />.
Next, in your Vue component, you need to gather the FormData so that it becomes possible to send the file to the server. Files have to be handled slightly differently to plain text fields and such.
Add this to your methods object:
gatherFormData() {
const data = new FormData();
data.append('resume', this.$els.resume.files[0]);
return data;
}
In your updateProfile method you now need to send this data off to the server as a POST request.
updateProfile(e) {
e.preventDefault();
var self = this;
this.form.startProcessing();
$.ajax({
url: '/route/to/controller',
data: this.gatherFormData(),
cache: false,
contentType: false,
processData: false,
type: 'POST',
headers: {
'X-XSRF-TOKEN': Cookies.get('XSRF-TOKEN')
},
success: function (response) {
self.form.finishProcessing();
console.log(response)
},
error: function (error) {
self.form.setErrors(error.responseJSON);
}
});
},
Finally, in your controller method, you can now handle the file as normal
(e.g., $request->file('resume');)
Handling files with Laravel really is a breeze – you just need to make sure you're actually getting them to the server ;)
Related
I am trying to post a file (will be of type pdf or image), uploaded by the user in a form. The file will be taken by an AngularJS directive set 'onChange', sent through 'myPostr' function which is supposed to post my file to 'api/' so it can be received by PHP. Atm, PHP echoes empty arrays, atleast having the headers - 200 OK.
This my HTML:
<input name="file" class="form-control-file" my-directive type="file" accept="application/pdf">
This my simplified AngularJS script:
application.directive('myDirective', function(myPostr){
return{
restrict: 'A',
scope: true,
link: function(scope, element){
element.bind('change', function(){
if (element[0].files[0].type == 'application/pdf') {
var form = new FormData();
form.append('form', element[0].files[0])
myPostr(form, function(callback){
console.log(callback);
}) //or imagetype to be implemented
application.factory('myPostr', function($http){
return function (data, callback) {
$http.post('api/', {
data: data,
headers: {'Content-type':undefined}
})}
});
'myPoster' works fine for json data (form variables)
This are the multiple ways I've tried in PHP to display the received data:
//isset($_FILES['file']) returns false
$response = json_decode(file_get_contents('php://input'),true);
header('Content-Type: application/json');
echo json_encode($response); //or
//echo json_encode($_FILES);
All return this in the network console
Extra info: these are the console logs of the uploaded files
I have tried majority of other questions here and other solutions and nothing has worked so far.
What I am trying to accomplish is upload images before Laravel's validation takes place, obviously I can't use the create function because it wont be hit until validation succeeds so I have made a custom function to do the file saving server side and trying to use Ajax to call that function every time a file is selected.
Current issue: doesn't seem like my Ajax is running on debugging its being skipped over,
second issue: I have a csrf token in my master template do i still need to add the ajax setup? if so is the way i am doing it correct.
Route:
Route::post('/upload', 'UploadController#uploadSubmit');
View:
<div>
<input type="file" id="fileupload" name="photos[]" data-url="/upload" multiple />
<br />
<div id="files_list"></div>
<p id="loading"></p>
<input type="hidden" name="file_ids" id="file_ids" value="" />
</div>
Ajax call:
$(document).ready(function(){
$("input").change(function(){
alert('triggered');
debugger;
$('#fileupload').fileupload({
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $(meta[name="csrf-token"]).attr('content')
}
dataType: 'json',
add: function (e, data) {
$('#loading').text('Uploading...');
data.submit();
},
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$('<p/>').html(file.name + ' (' + file.size + ' KB)').appendTo($('#files_list'));
if ($('#file_ids').val() != '') {
$('#file_ids').val($('#file_ids').val() + ',');
}
$('#file_ids').val($('#file_ids').val() + file.fileID);
});
$('#loading').text('');
}
});
});
});
});
Controller:
public function uploadSubmit(Request $request){
$files = [];
dd(request());
foreach($learnerFiles as $key => $learnerFile){
if(count($learnerFile) > 0){
$path = $learnerFile->storeAs('public/uploads/learners', request('idNumber').'_'.$key.'.'.$learnerFile->extension());
$search = 'public/' ;
$trimmed = str_replace($search, '', $path) ;
//dd($learnerFiles);
$file = FileUpload::create([
'user_id' => $learner->id,
'file_name' => $key,
'path' => $trimmed
]);
}
else{
}
$file_object = new \stdClass();
$file_object->name = $key;
$file_object->size = round(Storage::size($path) / 1024, 2);
$file_object->fileID = $learner->id;
$files[] = $file_object;
}
return response()->json(array('files' => $photos), 200);
}
I'm using the following method to upload images using Ajax call and Laravel back-end.
var uploader = $('#image-uploader[type="file"]');
var data = new FormData();
$.each(uploader.files, function() {
data.append('image[]', this);
});
data.append('_token', $('[name="csrf-token"]').attr('content'));
var url = '/upload'; //Or any target path with post method
$.ajax({
url: url,
method: 'POST',
data: data,
processData: false,
contentType: false,
success: function(data) {
alert('succeed');
}
});
Consider you can access to image files in server-side using $_POST['image] array.
Hope this helps you.
I am developing SPA using VueJS, Laravel 5.3 and Passport Authentication module.
My Code upto now. and I can get file name selected. Working fine but how to send selected files to make post request to upload the files to the server?
<script>
import {mapState} from 'vuex'
export default{
computed: {
...mapState({
userStore: state => state.userStore
})
},
data () {
return {
fax: {
files: '',
image: ''
}
}
},
methods: {
onFileChange (e) {
this.fax.files = e.target.files || e.dataTransfer.files
if (!this.fax.files.length) {
return
}
console.log(this.fax.files)
}
},
created () {
this.$store.dispatch('setUserDid')
}
}
</script>
<template>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" multiple #change="onFileChange">
<input type="text" name="group" >
<ul>
<li v-for="file in fax.files">
{{ file.name }}
</li>
</ul>
</template>
Upto now, I can get file names displayed on my page using {{fax.files}}. How to make post request so that i can catch the file from my server side (API endpoint)? I tried googling and coding but i could not able to do.
Ok I managed to get this working. Before the file upload I had an array that I was posting via Ajax as you can see below.
I modified it to look like the below in order handle file uploads.
Basically you need to send through a FormData object when uploading files. Uses a FormData object by default when submitting a form - but when only posting a array you need to first append those array values to the FormData object.
You should be able to make sense of the code below...
var formData = new FormData();
jQuery.each(this.comment.file, function(i, file) {
formData.append('file[]', file);
});
formData.append('body', this.comment.body);
formData.append('comments_room_id', this.comment.comments_room_id);
formData.append('id', this.comment.id);
formData.append('name', this.comment.name);
this.$http.post('/api/comment/store', formData).then(function (response) {
I was wondering if i could get a bit of advice.
Im trying to upload a file using jquery while keeping the user on the same page.
Whatever i try isnt working. I was wondering if someone could have a look and tell me where im going wrong.
My HTML is
<form id="import" enctype="multipart/form-data" action="/ajax/postimport" method="POST">
<div class="form-group">
<input type="file" name="filename" id="filename" />
</div>
<button type="button" id="importSave">Import</button>
</form>
This is my jquery
$("#importSave").click(function()
{
$.ajax({
url: '/ajax/postimport',
type: 'POST',
dataType: 'json',
contentType: false,
processData: false,
data: {file: $(#filename).val()},
success: function(data)
{
alert(data.result)
},
error: function(textStatus, errorThrown)
{
}
});
});
and then my PHP, which is Laravel 4
if (Input::hasFile('filename')) {
$file = Input::file('filename');
$destPath = public_path() . '/uploads/';
$filename = str_random(10) . '_' . $file->getClientOriginalName();
$uploadSuccess = $file->move($destPath, $filename);
}
It is not possible to upload files by just using the jQuery ajax function. You will need to use a FormData object to do this. The problem with Formdata is that it is not supported in all browsers. If you do want to use it, you can always find plenty tutorials like this one.
You can also use a jQuery plugin that does the work for you. :)
It is not possible to do like this. you are just making post ajax request with only one field file: $(#filename).val().
So you need to use ajax upload library like.
There are several alternatives. But I like most are
http://www.plupload.com/
http://www.uploadify.com/
First of all I'd like to ask that you don't suggest I turn to a jQuery plugin to solve my issue. I'm just not willing to make my app work with a plugin (and it prevents me from learning!)
I have a form with a bunch of fields that I'm passing to my backend via the use of jQuery's $.post() This is what I have as my jQuery function:
$.post(
"/item/edit",
$("#form").serialize(),
function(responseJSON) {
console.log(responseJSON);
},
"html"
);
This is how I opened my form:
<form action="http://localhost/item/edit" method="post" accept-charset="utf-8" class="form-horizontal" enctype="multipart/form-data">
This was auto generated by codeigniter's form_open() method (hence why action="" has a value. Though this shouldn't matter because I don't have a submit button at the end of the form)
Within my #form I have this as my file input: <input type="file" name="pImage" />
When the appropriate button is hit and the $.post() method is called, I have my backend just print the variables like so: print_r($_POST) and within the printed variables the 'pImage' element is missing. I thought that maybe files wouldn't come up as an element in the array so I went ahead and just tried to upload the file using this codeigniter function: $this->upload->do_upload('pImage'); and I get an error: "You did not select a file to upload."
Any idea as to how I can overcome this problem?
You cannot post an image using AJAX, i had to find out here as well PHP jQuery .ajax() file upload server side understanding
Your best bet is to mimic an ajax call using a hidden iframe, the form has to have enctype set to multipart/formdata
Files wont be sent to server side using AJAX
One of the best and simplest JQuery Ajax uploaders from PHP LETTER
all you need is include js in your header normally and Jquery code will be like below
$.ajaxFileUpload({
url:'http://localhost/speedncruise/index.php/snc/upload/do_upload',
secureuri:false,
fileElementId:'file_upload',
dataType: 'json',
data : {
'user_email' : $('#email').val()
},
success: function (data, status) {
// alert(status);
// $('#avatar_img').attr('src','data');
}
,
error: function (data, status, e) {
console.log(e);
}
});
wish this can help you
I can't do this with codeigniter and Ajax, I pass the image to base64 and in the controller I convert into a file again
//the input file type
<input id="imagen" name="imagen" class="tooltip" type="file" value="<?php if(isset($imagen)) echo $imagen; ?>">
//the js
$(document).on('change', '#imagen', function(event) {
readImage(this);
});
function readImage(input) {
var resultado='';
if ( input.files && input.files[0] ) {
var FR= new FileReader();
FR.onload = function(e) {
//console.log(e.target.result);
subirImagen(e.target.result);
};
FR.readAsDataURL( input.files[0] );
}
}
function subirImagen(base64){
console.log('inicia subir imagen');
$.ajax({
url: 'controller/sube_imagen',
type: 'POST',
data: {
imagen: base64,
}
})
.done(function(d) {
console.log(d);
})
.fail(function(f) {
console.log(f);
})
.always(function(a) {
console.log("complete");
});
}
//and the part of de controller
public function sube_imagen(){
$imagen=$this->input->post('imagen');
list($extension,$imagen)=explode(';',$imagen);
list(,$extension)=explode('/', $extension);
list(,$imagen)=explode(',', $imagen);
$imagen = base64_decode($imagen);
$archivo='archivo.'.$extension;
file_put_contents('imagenes/'.$archivo, $imagen);
chmod('imagenes/'.$archivo, 0777); //I use Linux and the permissions are another theme
echo $archivo; //or you can make another thing
}
ps.: sorry for my english n_nU