I'm trying to upload a file to a laravel backend via axios.
When a user clicks on the file input I get the file object, append it to the formData object post it to the backend, but for some reason, when I try to get the file on the backend I get an empty array.
here is my code:
<template>
<div>
<input type="file" #change="uploadFile" ref="file">
<button #click="submitFile">Upload!</button>
</div>
uploadFile(){
this.Images = this.$refs.file.files[0];
const formData = new FormData();
formData.append('file', this.Images);
const headers = { 'Content-Type': 'multipart/form-data' };
axios.post(this.baseUrl+'test-file-uploads', formData, { headers }).then((res) => {
res.data.files; // binary representation of the file
res.status; // HTTP status
});
}
public function testUploads(Request $request){
return [$request->file('file')];
return $this->uploadFiles($request,108,'props_and_set');
}
Use $request->hasFile('file') to see if the backend is able to get the file from the front end and then call the storage methods on the file.
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'm using FormData to send a file from ionic with angular to PHP, but in the PHP backend when you make var dump $_FILES appear empty.
This is my code in .ts:
file: File;
changeListener($event): void {
this.file = $event.target.files[0];
console.info(this.file); //First console info
const formData = new FormData();
const blobFile = new Blob([this.file], { type: this.file.type });
formData.append("file", blobFile, "filename");
this.myService.testing(formData).subscribe( resp => {
},(error)=>{
console.info(error);
})
}
In the service:
testing(data) {
return this.http.post(url, body, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
}
The PHP Backed :
$postdata = file_get_contents("php://input"); // this shows me the contents of the file
var_dump($_FILES); // returns an empty array
So, what's my mistake? Am I sending badly from Ionic or am I getting bad in PHP ?
I'm using codeigniter 3
Thanks !
tl;dr:
Using Angular 6 on the front end and PHP with Phalcon on the backend, I can send JSON data or a File with no problem but I am having a problem sending both in the same request.
Previously I was sending JSON data to the server using something like this
const HTTP_OPTIONS = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
}),
observe: 'response'
};
post(endPoint: string, body: object): Observable<any> {
return this.http.post<any>(this.apiUrl + endPoint, body, HTTP_OPTIONS)
.pipe(
tap(result => this.log(JSON.stringify(result, null, 2))),
catchError(this.handleError('post', []))
);
}
And I was able to get the data from PHP using Phalcon with
$app = new \Phalcon\Mvc\Micro();
$app->post('/upload', function() use ($app) {
$input = $app->request->getJsonRawBody();
// $input now contains my JSON data
});
Some time later, I needed to send a file so I used this answer with some minor modifications:
postFile(fileToUpload: File, endpoint: string): Observable<any> {
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
return this.httpClient
.post(endpoint, formData, { headers: {'Authorization': this.jwt} }).pipe(
tap(result => this.log(JSON.stringify(result, null, 2))),
catchError(this.handleError('post', []))
);
}
And I received my file with no problems using the documentation as a guide:
$app->post('/uploads', function() use ($app) {
if ($app->request->hasFiles() == true) {
foreach ($app->request->getUploadedFiles() as $file) {
$file->moveTo('files/' .$file->getname());
}
} else {
$app->response->setStatusCode(400)->sendHeaders();
$app->response->setJsonContent(['error' => 'no file']);
return $app->response;
}
});
The problem: Now I would like to send both a file and some JSON data at the same time. I can always just upload the file and then send the data separately but I don't think that's the right way to do it. I don't want to make more than the minimum number of network calls.
What I've tried: Using the file upload code and simply appending another field to my FormData object with my JSON data
formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', JSON.stringify(data));
and a variation of that
formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', new Blob([JSON.stringify(data), {type: 'application/json'}]);
Either way, on the backend I can get the file but $app->request->getJsonRawBody and $app->request->getRawBody are empty.
I also tried using the original JSON-sending code and just changing a bit to include the file but with no success.
post(fileToUpload: File, data: CustomData): Observable<any> {
this.messageService.add('uploaded file');
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
formData.append('data', JSON.stringify(data), 'data');
return this.http
.post(this.apiUrl + 'uploads/', {'data': data, 'file': fileToUpload}, HTTP_OPTIONS).pipe( // file is empty on the server like this
tap(result => this.log('POST file :\n' + JSON.stringify(result, null, 2))),
catchError(this.handleError('post', [], 'fileUpload'))
);
}
I can easily send either my JSON data or the file but not both.
I searched the Phalcon documentation and several QAs on sending files and/or JSON with Angular but I cannot figure out how to make this work.
You are sending json as text in post request, so instead of $app->request->getJsonRawBody you should try something like
$rawJson=$app->request->getPost('data');
$object=json_decode($rawJson);
you can get your json as #Błażej Kowalczyk said
$this->request->getPost()
and you can check for files and get them
if ($this->request->hasFiles()) {
foreach ($this->request->getUploadedFiles() as $file) {
// $file is an instance of Phalcon\Http\Request\File
var_dump($file->getName());
}
}
check these pages for more information
https://docs.phalconphp.com/3.4/en/api/phalcon_http_request
https://docs.phalconphp.com/3.4/en/api/phalcon_http_request_file
Hello friends I created a project in angular 4 I want to upload an image and sent request to the PHP file but form-data can't append values and images.
please help me
I include FormGroup, FormControl, FormBuilder, Validators, Http
const Image = this.com_Image.nativeElement;
if (Image.files && Image.files[0]) {
this.comImageFile = Image.files[0];
}
const ImageFile: File = this.comImageFile;
// [enter image description here][1]
let formData = new FormData();
formData.append('companyName', value.companyName);
formData.append('username', value.username);
formData.append('uploadFile', ImageFile, ImageFile.name);
console.log(formData);
Html
<input #fileSelect type="file" class="form-control" (change)="onFileChanged($event)" accept=".jpg, .png"/>
component
export class FileUploadComponent {
#ViewChild('fileSelect') fileSelectInput: ElementRef;
fileToUpload: any;
onFileChanged(event) {
// https://stackoverflow.com/questions/13602039/e-srcelement-is-undefined-in-firefox
this.fileToUpload = (event.srcElement || event.target).files;
let formData: FormData = new FormData();
formData.append('file', this.fileToUpload[0]);
this.createOrUpdateResource(formData);
}
// https://stackoverflow.com/questions/48059121/angular4-file-upload-put-request-fails,
so making this POST
private createOrUpdateResource(formData: FormData) {
this.http.post<any>(`http://localhost:8080/upload`, formData).subscribe((res) => {
//success
}, error => {
//error
});
}
}
Have you tried to pass only name and value for the image?
For file management (in general) this has worked for me:
formData.append('uploadFile', ImageFile);
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 ;)