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.
Related
I'm using Angular with PHP and trying to post an object. Request status is 200, but $_POST array is empty. Data I'm sending is a valid JSON Object.
sendTweet(){
if(!this.username || !this.tweet){
alert("Enter username or tweet");
return;
}
const newTweet:Tweet = {
username: this.username,
tweet: this.tweet
}
//Call Service
this.testService.postTweet(newTweet).subscribe((response)=>{console.log(response)},
(err:any)=>{
console.log(err.message);
});
}
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
postTweet(tweet:Tweet):Observable<Tweet>{
const url = `${this.apiUrl}/?page=submit&action=add`;
return this.http.post<Tweet>(url,tweet, httpOptions);
}
PHP:
if (isset($_POST['tweet'])&&isset($_POST['username'])) {
//Sending tweet to the db
} else{
print_r($_POST);
}
i dont know if its a backend problem with php but in my project i have it a little bit diferent (i am using .net core for backend)
for example in my project:
//service component WebScrapLinkService
get(): Observable<Any[]> {
return this.http.get<Any[]>(this.url)
.pipe(map(res => res));
}
//main component
getRegisters() {
this.getProductsSub = this.crudService.get()
.subscribe(data => {
this.registers = data;
})
}
//variables
public registers: Array<object> = [];
//the service goes in the constructor
private crudService: WebScrapLinkService
this works fine for me, i hope it is useful for you
It was just me not knowing that in PHP you have to parse HTTP_RAW_POST_DATA in order to get the data.
i use Laravel-filepond and Vue FilePond.
but FilePond send a blank request to server.
this is my codes:
*UserComponent.vue
<template>
<div class="container">
<file-pond
name="Profile"
ref="pond"
label-idle="drag & drop"
v-bind:allow-multiple="false"
accepted-file-types="image/jpeg, image/png"
v-bind:files="userFile"
v-bind:server="{
url: '/panel/filepond',
timeout: 7000,
process: {
url: '/process',
method: 'POST',
headers: {
'X-CSRF-TOKEN': this.get_meta('csrf-token'),
},
}
}"
v-on:init="handleFilePondInit"/>
</div>
</template>
<script>
import vueFilePond, {setOptions} from 'vue-filepond';
import 'filepond/dist/filepond.min.css';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginImageEdit from 'filepond-plugin-image-edit';
const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview);
export default {
data() {
return {
userFile: [],
}
},
methods: {
handleFilePondInit: function () {
console.log('FilePond has initialized');
}
},
components: {
FilePond
},
}
</script>
FilePondController.php Original file
<?php
namespace Sopamo\LaravelFilepond\Http\Controllers;
use function dd;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Sopamo\LaravelFilepond\Filepond;
class FilepondController extends BaseController
{
private $filepond;
public function __construct(Filepond $filepond)
{
$this->filepond = $filepond;
}
public function upload(Request $request)
{
dd($request->all());
}
}
when I upload a file on client side (in default response with 422), I can not find it on my server.
FrameWorks & Repository is on last version.
Response
[]
According to the author, you are sending the metadata instead of the file itself. I solved this using the advanced custom process function that you can found in documentation. There you can find the comments about what almost every part of the code does.
data() {
return {
server: {
url: 'http://base-url.test',
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
const formData = new FormData();
formData.append(fieldName, file, file.name);
const request = new XMLHttpRequest();
request.open('POST', 'url-to-post-to');
request.setRequestHeader('X-CSRF-TOKEN', 'your-csrf-token');
request.upload.onprogress = (e) => {
progress(e.lengthComputable, e.loaded, e.total);
};
request.onload = function () {
if (request.status >= 200 && request.status < 300) {
load(request.responseText);
} else {
error('Error');
}
};
request.send(formData);
return {
abort: () => {
request.abort();
abort();
},
};
},
},
}
},
Then you only need to bind it:
<template>
<div class="container">
<file-pond
name="Profile"
ref="pond"
label-idle="drag & drop"
v-bind:allow-multiple="false"
accepted-file-types="image/jpeg, image/png"
v-bind:files="userFile"
v-bind:server="server"
v-on:init="handleFilePondInit" />
</div>
</template>
responseText is the unique Id from the server. Maybe you want to emit it to parent component:
data() {
return {
server: {
url: 'http://base-url.test',
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
const thisReference = this;
// Other code
request.onload = function () {
if (request.status >= 200 && request.status < 300) {
thisReference.
thisReference.$emit('my-event', request.responseText);
load(request.responseText);
} else {
error('Error');
}
};
// Other code
},
},
}
},
Pretty similar if you want to know what file has been reverted (in this case, you need to response from server with the same id you sent):
data() {
return {
server: {
// Process, url, etc.
revert: {
url: '/url-to-delete',
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': 'your-csrf-token'
},
onload: (idDeleted) => this.$emit('my-event', idDeleted)
},
},
}
},
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']
I have a export csv function, it worked fine with laravel. But now I want to call export function via ajax and use method post, but I there is no respone. I can send a variable from laravel controller to response, but can not send a file download.
Here is my code :
route.php
Route::get('/title/show', 'TitleController#show');
Route::post('/title/show', 'TitleController#exportFromDB');
show.blade.php
<script>
$(document).ready(function () {
$('#exportFromDB').click(function () {
$.ajax({
url: "",
type: "post",
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
data: {},
success: function (response) {
var a = document.createElement("a");
a.href = response.file;
a.download = response.name;
}
})
})
})
TitleController.php:
$dataExport['Oversea'] = $dataOversea;
$this->titleRepository->export('csv', $properties, $dataExport);
TitleRepository.php
public function export($type, $properties, $data)
{
if (in_array($type, self::EXPORT_TYPE)) {
try {
return Excel::create($properties['_title'], function ($excel) use ($data, $properties) {
$excel->setTitle($properties['_title']);
$excel->setCreator($properties['_creator'])
->setCompany($properties['_company']);
$excel->setDescription($properties['_description']);
$excel->sheet('Sheet', function ($sheet) use ($data) {
foreach ($data as $item) {
$sheet->fromArray($item);
}
});
})->export($type);
} catch (Exception $error) {
throw $error;
}
}
}
How can I fix them ? Thank !
Try this -
Don't write the code for export in your controller method, instead just save the excel file in your public folder.
Your controller method should return the filename.
On your ajax success do this -
location.href = path/to/file/property_title.xls
So replace your this line
->export($type);
with
->store($type, 'public/reports/', true);
I see your ajax url null value
Change it to
url : "{{ action('TitleController#exportFromDB') }}"
After that, response is data you return in controller
success: function (response) {}
I installed the maatwebsite/excel package and was able to do it without writing any javascript. All you need to do is setup a link (or typical form post if you prefer) to an action like so:
public downloadItemsExcel() {
$items = Item::all();
Excel::create('items', function($excel) use($items) {
$excel->sheet('ExportFile', function($sheet) use($items) {
$sheet->fromArray($items);
});
})->export('xls');
}
This works for csv/excel files alike. There is no reload of a page in the browser.
First you have to change POST method to GET.
For ajax you can do it like this:
$(document).ready(function () {
$('#exportFromDB').click(function () {
$.get('/title/show, function(data){
window.location = '/title/show=' + data;
});
})
})
My goal to achieve is:
first to insert new database record with http post, resolve with stateProvider and grab the new id and change view and stateParams.
i have this code for my http post service
myApp.service('postService', ['$http', function($http) {
this.insertNew = function() {
$http.post('create_new.php')
.success(function(data) {
return data;
});
};
create_new.php returns the ID like this (it works, proved with console)
return json_encode($data);
and the stateProvider looks like this (section)
$stateProvider
.state('newRecord', {
resolve: {
newArtID: ['postService',
function(postService) {
return postService.insertNew();
}]
},
params: {
artID: <-- new ID from DB
},
i did tests with stateParams in serval variations (in resolve and by params). how can i bring the new ID to stateParams, so i can access from the views?
Thanks for any help!
I'm not so sure your oder of operations is correct. params is for when you already have that data. You should return the data from your resolve, then you can access it in your scope, for ex:
Service:
.service('postService', function ($http) {
this.insertNew = function () {
return $http.post('create_new.php').then(function (data) {
return data;
});
}
})
Route:
$stateProvider
.state('newRecord', {
views: {
"main": {
controller: 'SomeCtrl',
templateUrl: '...'
}
},
resolvedId: {
newArtID: function (postService) {
return postService.insertNew().then(function (response) {
return response;
});
}
}
})
Controller:
.controller('SomeCtrl', function (resolvedId) {
var newID = resolvedId.id; //depending on what is returned
});