I'm using Aurelia with PHP as backend. Here is my view with its model:
home.html
<template>
<require from="datepicker.js"></require>
<form submit.delegate="submit()">
<input value.bind="name"></input>
<input value.bind="age"></input>
<button type="submit" name="submit">Submit
</button>
</form>
</template>
home.js
import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';
import 'fetch';
#inject(HttpClient)
export class Home {
name;
age;
constructor(http) {
this.http = http;
}
submit() {
this.jsonobj = {
'name': this.name,
'age': this.age
};
if (this.jsonobj.name && this.jsonobj.age) {
this.http.fetch('dist/components/ses.php', {
method: 'post',
body: JSON.stringify(this.jsonobj)
})
.then(response => response.json())
.then(data =>
{
console.log(data);
});
}
}
}
And here is the PHP script:
ses.php
<?php
session_start();
$word = 'lol';
if(!isset($_SESSION['username'])){
$_SESSION['username'] = 'kil';
}
$input = file_get_contents('php://input');
$input_json_array = json_decode($input);
echo json_encode(array('item' => $_SESSION['username']));
?>
I expect that after the first call to the script, $_SESSION['username'] will be set to 'kil'. So on next ajax post !isset($_SESSION['username'] wont evaluate to true but it does which means PHP session isn't working.
By default fetch (the web standard that aurelia-fetch-client is built on) does not send cookies. You'll need to use credentials: 'include' in your request init object.
Two great resources for fetch:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
https://davidwalsh.name/fetch
The codez:
this.http.fetch('dist/components/ses.php', {
credentials: 'include', // <-------------------------------------
method: 'post',
body: JSON.stringify(this.jsonobj)
})
Related
Description
I have a table, where i collect values from checkboxes with JavaScript. This values should be send to a protected API route in a Laravel backend.
I use the standard Laravel auth setup (out of the box).
Question
What do I have to send with the JavaScript post request for authentication and how do i do that? Can i add a auth token or something like that to the headers?
At the moment i get the reponse:
"This action is unauthorized".
exception: "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException"
Edit
At the current point of my research the api token seems to be a simple solution for my case. But i can't figure out how to attach the api token to the JavaScript post request.
Thats the JavaScript function for collecting the values storing them in objects.
import SaveData from "../api/SaveData";
export default async function SaveMultipleReports() {
const table = document.getElementById("reports-dashboard");
const rows = table.querySelectorAll("div[class=report-tr]");
let reports = [];
for (const row of rows) {
const checkbox_visible = row.querySelector("input[name=visible]")
.checked;
const checkbox_slider = document.querySelector(
"input[name=show_in_slider]"
).checked;
const report = {
id: row.id,
visible: checkbox_visible,
show_in_slider: checkbox_slider
};
reports.push(report);
}
console.log(reports);
const response = await SaveData("/api/reports/update", reports);
console.log(response);
}
And that is the SavaData function:
export default async function SaveData(api, data) {
const token = document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content");
const url = window.location.origin + api;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": token,
Accept: "application/json"
},
body: JSON.stringify(data)
});
const result = await response.json();
return result;
}
And thats the line in the api.php:
Route::middleware("can:administration")->post("reports/update", "ReportsController#UpdateAll");
The whole repo is here.
Thanks for your time in advance :)
Edit 2
For now i managed it without JavaScript. Put all the values, i want to update in form and load a hidden input for the ID of every object (the ID is needed for the controller afterwards).
Thanks to this post.
{!! Form::open(["route" => ["admin.reports.multiupdate"], "method" => "PUT", "class" => "report-table"]) !!}
... // some HTML
#foreach ($reports as $report)
<div class="report-tr">
<input type="hidden" name="reports[{{$loop->index}}][id]" value="{{$report->id}}">
<div class="td-name">
<p class="td-text">{{$report->name}}</p>
</div>
<div class="td-flex">{{$report->body}}</div>
<div class="tr-wrapper">
<div class="checkbox-visible">
<div class="checkbox-container">
<input class="checkbox" type="checkbox" name="reports[{{$loop->index}}][visible]" value="1" checked>
<span class="checkmark"></span>
</div>
<label class="table-label" for="visible">Sichtbar</label>
</div>
<div class="checkbox-slider">
<div class="checkbox-container">
<input class="checkbox" type="checkbox" name="reports[{{$loop->index}}][show_in_slider]" value="1"
{{($report->show_in_slider == 1 ? "checked" : "")}}>
<span class="checkmark"></span>
</div>
<label class="table-label" for="show_in_slider">Im Slider</label>
</div>
<div class="td-buttons">
...
#endforeach
<button class="floating-save">
#svg("saveAll", "saveAll")
</button>
{!! Form::close() !!}
And a snippet from the Controller:
public function MultipleUpate(ReportUpdate $request)
{
$reports = $request->input("reports");
foreach ($reports as $row) {
$report = Report::find($row["id"]);
// giving the checkbox 0, if it isn't checked
$isVisible = isset($row["visible"]) ? 1 : 0;
$inSlider = isset($row["show_in_slider"]) ? 1 : 0;
$report->visible = $isVisible;
$report->show_in_slider = $inSlider;
$report->new = false;
if ($report->save()) {
$saved = true;
}
}
if ($saved == true) {
$request->session()->flash("success", "Änderungen gespeichert!");
} else {
$request->session()->flash("error", "Das hat nicht geklappt!");
}
return back();
The ReportUdpate function contains only that:
public function authorize()
{
return true;
}
public function rules()
{
return [
"visible" => "nullable",
"show_in_slider" => "nullable"
];
}
You are talking about authentication but using an authorization middleware. There is a difference between the two.
Read about it here: https://medium.com/datadriveninvestor/authentication-vs-authorization-716fea914d55
With that being said, what you are looking for is an authentication middleware that protects your routes from unauthenticated users. Laravel provides a middleware called Authenticate out of the box for this specific purpose.
Change your route to be like so:
Route::middleware("auth")->post("reports/update", "ReportsController#UpdateAll");
I got the problem for getting invalid value from formdata. The value is correct in this.fileData with size 5701, but get invalid value when it convert to form data. It becomes {} when I console.log
form data. When I console.log(formdata[0]) getting value undefined.
The code I expect that when the formdata post to backend, the file is valid. But backend gets the 0 size picture. I guess that the problem is from formdata, because formdata gets nothing.
about html
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h3>Choose File</h3>
<div class="form-group">
<input type="file" name="image" (change)="fileProgress($event)" />
</div>
<div *ngIf="fileUploadProgress">
Upload progress: {{ fileUploadProgress }}
</div>
<div class="image-preview mb-3" *ngIf="previewUrl">
<img [src]="previewUrl" height="300" />
</div>
<div class="mb-3" *ngIf="uploadedFilePath">
{{uploadedFilePath}}
</div>
<div class="form-group">
<button class="btn btn-primary" (click)="onSubmit()">Submit</button>
</div>
</div>
</div>
</div>
about typescripts
import { Component, OnInit, Input } from '#angular/core';
import { HttpClient, HttpEventType } from '#angular/common/http';
import { UploadService } from '../../../model/shared/api/upload.service';
import { HttpHeaders } from '#angular/common/http';
import { LoginComponent } from '../../account/auth/login/login.component';
import { HttpClientModule } from '#angular/common/http';
//import * as myGlobals from './globals';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
//'Authorization': 'my-auth-token'
})
};
#Component({
selector: 'cd-upload',
templateUrl: './upload.component.html',
styleUrls: ['./upload.component.scss']
})
export class UploadComponent implements OnInit{
fileData: File = null;
previewUrl:any = null;
fileUploadProgress: string = null;
uploadedFilePath: string = null;
constructor(private uploadService: UploadService,private httpClient: HttpClient,private http: HttpClient) {
}
fileProgress(fileInput: any) {
this.fileData = <File>fileInput.target.files[0];
this.preview();
}
preview() {
// Show preview
var mimeType = this.fileData.type;
if (mimeType.match(/image\/*/) == null) {
return;
}
var reader = new FileReader();
reader.readAsDataURL(this.fileData);
reader.onload = (_event) => {
this.previewUrl = reader.result;
}
}
onSubmit() {
//here is the problem
const formData = new FormData();
formData.append('files', this.fileData);
console.log(this.fileData);
console.log(formData[0]);
console.log(formData);
this.http.post('http://api', formData, {
reportProgress: true,responseType: 'blob' as 'json',
observe: 'events'
})
//here is the problem
}
ngOnInit(){}
}
here is the backend code with python FLask
#app.route('/bupload', methods=['GET', 'POST'])
def bupload():
result="Upload done";result1="Upload fail";result2="File not allowed";result3="No selected file";result4="No file part";form="123";
print(request.files); print(request.files['files']);#request.files=ImmutableMultiDict(request.files).to_dict(flat=False);print(request.files['file']);
#upload_First(form, request.files['files'])
if 'files' not in request.files:
flash('No file part');print(file);
return result4
file = request.files['files'];print(file);print("#0");
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return result3
if file and allowed_file(file.filename):
if(upload_First(form, file)):
flash('Upload done');
print("#");
return result
else:
flash('Upload fail')
return result1
else:
flash('File not allowed')
return result2
ps:
backend can get the value ImmutableMultiDict([('files', )]), but the IDF.jpg is 0 size
ps2:
console.log(formData.get('files')); show as below
File {name: "IDF.jpg", lastModified: 1574402253947, lastModifiedDate: Fri Nov 22 2019 13:57:33 GMT+0800 (), webkitRelativePath: "", size: 5701, …}
console.log(formData); show as below
FormData {}
_event.target.result will give the content of file
fileContent has to be sent to server
fileProgress(fileInput){
var file = <File>fileInput.target.files[0];
const formData = new FormData();
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (_event) => {
formData.append('photo', _event.target.result);
console.log(formData.get('photo'));
}
}
I'm usin react.js(ver 15) and i want to upload the files with yii2 api.
My code is as follows:
My component(in react):
import React, { Component } from 'react';
import Header from './Heaader';
/* global $ */
class New extends Component {
constructor(props){
super(props);
this.state = {
cates: [],
subcats: [],
radioSelected: "f"
};
}
submitted = (e) => {
e.preventDefault();
var file_data = $('#filee')[0].files;
var form_data = new FormData();
form_data.append('file', file_data);
$.ajax({
url: "http://blog.dev/ads",
type: "POST",
data: form_data,
contentType: false,
cache: false,
processData:false,
success: function(data){
console.log(data);
},
error: function(){}
});
};
render(){
return (
<div>
<Header isNew="true" />
<div style={{marginTop: 2 + 'em'}}>
<form onSubmit={this.submitted}>
<input type="file" id="filee" />
<button type="submit">Sub</button>
</form>
</div>
</div>
);
}
Server Side:
In my controller:
<?php
namespace frontend\controllers;
use Yii;
use yii\rest\ActiveController;
class AdsController extends ActiveController
{
public $modelClass = 'frontend\models\Ads';
public function behaviors()
{
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => \yii\filters\Cors::className(),
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
public function actions()
{
$actions = parent::actions();
unset($actions['create']);
return $actions;
}
public function actionCreate()
{
print_r($_FILES);
}
}
My problem is that $_FILES array is empty!
When I send data other than the file, $_POST works without problems(While this is the case in ajax request: processData:true and contentType:true ).
but $_FILES is empty.
Please guide me and tell me where the problem is?
Make sure your form has the correct encoding i.e <form enctype=multipart/form-data> for file uploads. this is most likely the reason why your $_FILES is empty
Yii 2 specifies a uniform API for fetching/saving uploads by using UploadedFile::getInstance($model, 'imageFile'); from the yii\web\UploadedFile; You should use it to access the uploads.
All the Best
Is it possible to pass a variable from controller to vuejs? I have read some answers but nothing seems to work for me. I want to pass the variable $url to vue. I have tried some thing like this
var url = {!! $url !!}; this gives me syntax error: unexpected token in app.js
example url http://eventregistry.org/json/suggestConcepts?prefix=sam&lang=eng&callback=JSON_CALLBACK
Controller
class SearchCompanyName extends Controller
{
public function getcompanyname($name)
{
return "http://eventregistry.org/json/suggestConcepts?prefix=" . $name . "&lang=eng&callback=JSON_CALLBACK";
}
public function index()
{
$url = $this->getcompanyname(Input::get("company_name_by_user"));
return view('searchcompany', ['url' => $url]);
}
}
vue app.js
Vue.component('search', require('./components/Searchnames.vue'));
const search = new Vue({
el: '#search',
data: {
},
method: {
getMessages: function(){
console.log('I am here')
}()
}
});
blade template
#section('content')
<div class="container">
{!! $url !!}
<search></search>
</div>
#endsection
If you want to declare your javascript variable in a script tag within a blade file, you need to put the variable in quotes like so
<script>
var url = '{{ $url }}';
</script>
You can use this package : https://github.com/laracasts/PHP-Vars-To-Js-Transformer
public function index()
{
JavaScript::put([
'foo' => 'bar',
'user' => User::first(),
'age' => 29
]);
return View::make('hello');
}
I can save all data varchar/text element from my form, but I can't save my path image.
Whats is wrong with my code?
Lets see my create.blade.php I can save value of var deadline but I can't save value of var path:
Form::open(array('url' => 'imagesLoker', 'files' => true))
<form class="form-horizontal">
<div class="box-body">
<div class="form-group">
{!!Form::label('Deadline Lowongan : ')!!}
{!!Form::date('deadline',null,['id'=>'deadline','class'=>'form-control','placeholder'=>'Deadline Lowongan'])!!}
</div>
<div class="form-group">
{!!Form::label('Image Lowongan : ')!!}
{!!Form::file('path') !!}
</div>
</div><!-- /.box-body -->
</form>
{!!Form::close()!!}
This is my Controller:
public function store(Request $request)
{
Lowongan::create($request->all());
return "data all";
}
This is my Ajax to create the data:
$("#createLoker").click(function(){
var datas = $('form').serializeArray();
var route = "http://localhost:8000/lowongan";
var token = $("#token").val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.post(route,{
deadline: $("#deadline").val(),
path: $("#path").val()
}).done(function(result){
console.log(result);
});
});
I don't know this is important or no to setting parse data in my Modal, but I just put this code in my Modal:
class Lowongan extends Model
{
protected $table = 'Lowongan';
protected $fillable = ['path','deadline'];
public function setPathAttribute($path){
$this->attributes['path'] = Carbon::now()->second.$path->getClientOriginalName();
$name = Carbon::now()->second.$path->getClientOriginalName();
\Storage::disk('local')->put($name, \File::get($path));
}
}
And the last I set the directory to save the image. This is setting in the config/filesystem:
'disks' => [
'local' => [
'driver' => 'local',
'root' => public_path('imagesLoker'),
],
I can save the data deadline but no for image :( .. If there is any idea for how to save the image path, I will be pleased to know it.
In your form you have to allow file upload option in laravel like.
Form::open(array('url' => 'foo/bar', 'files' => true))
check the file upload section of laravel doc
Hope it helps..
please follow these steps
in view
change {!!Form::file('path') !!} to {!!Form::file('file') !!}
In controller
please note i have set the upload path to root/public/uploads/ folder
public function store(Request $request)
{
$file = Input::file('file');
$path = '/uploads/';
$newFileName = Carbon::now()->second.$file->getClientOriginalName(). '.' . $file->getClientOriginalExtension();
// Move the uploaded file
$upSuccess = $file->move(public_path() . $path, $newFileName);
$result = file_exists(public_path() . $path . $newFileName);
$fileData =[
'fileType' => $file->getClientOriginalExtension(),
'filePath' => substr($path, 1) . $newFileName
];
Input::merge(array('path' => $fileData["filePath"]));
Lowongan::create($request->all());
return "data all";
}