ReactPHP --> File upload --> $request->getUploadedFiles() returns empty array - file-upload

I'm learning ReactPHP with the Book «ReactPHP for Beginners».
Everything worked fine, but now I'm on the section with file uploads.
There is a simple html form:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<title>ReactPHP App</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="row">
<form action="/upload" method="post" enctype="multipart/form-data" class="justify-content-center">
<div class="form-group">
<label for="file">Submit a file:</label>
<input type="file" name="file" id="file" accept="image/x-png,image/jpeg" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</body>
</html>
And the PHP Code witch receives the form data ist also very simple:
<?php
use Psr\Http\Message\ServerRequestInterface;
use React\EventLoop\LoopInterface;
use React\ChildProcess\Process;
use React\Http\Message\Response;
return [
'/' => function(ServerRequestInterface $request, LoopInterface $loop) {
$childProcess = new Process('cat pages/index.html', __DIR__);
$childProcess->start($loop);
return new Response(
200,
['Content-Type' => 'text/html'],
$childProcess->stdout
);
},
'/upload' => function (ServerRequestInterface $request, LoopInterface $loop) {
$files = $request->getUploadedFiles();
$file = $files['file'];
print_r($file);
return new Response(
200, ['Content-Type' => 'text/plain'], ''
);
}
];
If I choose a JPG-File and click «Submit», $request->getUploadedFiles() always returns an empty array. What's wrong here? I work on Mac OS X (10.15.7) and I tried with different browsers.

It looks like that server needs additional middlewares setup to properly handle file upload. You have to import it from React\Http\Middleware\ namespace.
$server = new Server($loop,
new StreamingRequestMiddleware(),
new RequestBodyBufferMiddleware(8 * 1024 * 1024), // 8 MiB
new RequestBodyParserMiddleware(8 * 1024 * 1024, 1), // 8 MiB
function (ServerRequestInterface $request) use ($router) {
return $router($request);
});
Those additional midlewares are specific for the web browser as long as ReactPHP is able to handle file upload if we are using curl, e.g.
$ curl --form file=#some_file_that_we_are_going_to_upload http://0.0.0.0:8080/upload
Please have in mind that path and port are related to example from book „ReactPHP for Beginners”

Related

controller not sending to view .net core

controller not sending to view . I m trying to send request from controller to view , but its not redirecting . controller always redirect to index page. when i summit the form . its always redirecting same index page ,
controller not sending to view .controller not sending to view
My controller is sending to another view. but its not working .
public IActionResult userLogin([FromBody] Users user)
{
string apiUrl = "https://localhost:44331/api/ProcessAPI";
var input = new
{
email = user.email,
password = user.password
};
string inputJson = (new JavaScriptSerializer()).Serialize(input);
WebClient client = new WebClient();
client.Headers["Content-type"] = "application/json";
// client.Encoding = Encoding.UTF8;
string json = client.UploadString(apiUrl + "/userLogin", inputJson);
// List<Users> customers = (new JavaScriptSerializer()).Deserialize<List<Users>>(json);
user = JsonConvert.DeserializeObject<Users>(json);
return View();
}
and the view page is
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#model myproject.Models.Users
#{
Layout = null;
}
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Inventory Management System</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
#* <link rel="stylesheet" type="text/css" href="./includes/style.css">*#
#*<script type="text/javascript" rel="stylesheet" src="~/js/main.js"></script>*#
</head>
<body>
<div class="overlay"><div class="loader"></div></div>
<!-- Navbar -->
<br /><br />
<div class="container">
<div class="alert alert-success alert-dismissible fade show" role="alert">
#*<?php echo $_GET["msg"]; ?>*#
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
#*<?php
}
?>*#
<div class="card mx-auto" style="width: 20rem;">
<img class="card-img-top mx-auto" style="width:60%;" src="./images/login.png" alt="Login Icon">
<div class="card-body">
<form id="form_login" >
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
#*<input asp-for="Name" type="text" class="form-control" id="name" required />*#
<input asp-for="email" type="email" class="form-control" id="log_email" placeholder="Enter email">
<small id="e_error" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" name="log_password" asp-for="password" id="log_password" placeholder="Password">
<small id="p_error" class="form-text text-muted"></small>
</div>
<button type="submit" class="btn btn-primary"><i class="fa fa-lock"> </i>Login</button>
<span>Register</span>
</form>
</div>
<div class="card-footer">Forget Password ?</div>
</div>
</div>
<input type="text" id="txtName" />
<input type="button" id="btnGet" value="Get Current Time" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#form_login").on("submit", function () {
var data = {
email: $("#log_email").val(),
password: $("#log_password").val(),
// Phone: $("#phone").val()
}
// data: $("#form_login").serialize(),
// var data = $("#form_login").serialize();
console.log(data);
$.ajax({
type: 'POST',
url: '/Process/userLogin',
// window.location.href = '#Url.Action("Process", "Dashboard")';
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
success: function (result) {
alert('Successfully received Data ');
console.log(result);
window.location.href = "Process/Dashboard";
// window.location.href = '#Url.Content("~/User/Home")';
// window.location.href = '#Url.Action("Process", "Dashboard")';
// window.location.href = DOMAIN + "/dashboard.php";
},
error: function () {
alert('Failed to receive the Data');
console.log('Failed ');
}
})
})
});
</script>
</body>
</html>
From your code, since you want to use JQuery Ajax to submit the form data to the action method, in the form submit event, you should use the event.preventDefault() to prevent the form submit action, then you can use JQuery Ajax to submit the form.
Second, does the Index page is the Process/Dashboard page? From your code, we can see in the Ajax success function, you will use the window.location.href to change the request URL, you can change the redirect page from here.

MVC Express - Data does not carry over in view once form is submitted

I am working on a very basic weather app to learn MVC architecture. However, I am having an issue with my page reloading once I submit the form and then data from that submission not coming over into the next newly rendered page.
Most of my logic for my page is in my controller.js file. In my view I have a form where the user fills in a city, and then my getWeather function makes an API call where it gets the city's temperature. From there my controller.js should re-render the index page, but pass in the string It is currently ${temp} °F in ${city}.
At least, that's how its supposed to work. Unfortunately when the page reloads the weather const is null and I then have my function catch the error and give me the message "that city is not available".
I have tested my API to make sure that it is correctly retrieving the data, by console.logging the res object, and I am getting that perfectly.
Also, I should note I bring in Weather function from my model. The only thing it does is test to see if the user inputted anything into the form and if they didn't it creates the error "Please enter the name of the city." I don't think it is the source of my issue or the fix for it.
I guess what I'm looking for is a way to prevent my page from reloading when I submit the form, or a way to not lose the data in my function when the page reloads. Any help would be greatly appreciated!
const axios = require('axios')
const API_KEY= "8d130a4fe5369b01d1fe629bccbe0926";
const Weather = require("../model/Weather")
exports.renderHomePAge = (req, res) => {
res.render("index")
}
exports.getWeather = (req, res, ) => {
const city = req.body.city
const url = `http://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=imperial`
const weather = new Weather(city)
weather.validateUserInput()
if(weather.errors.length){
res.render("index", {error: weather.errors.toString()})
} else {
axios.get(url)
.then((response)=>{
// console.log(response)
const {temp} = response.data.main
const {city} = response.data.city
res.render("index", {
weather: `It is currently ${temp} °F in ${city}.`
})
})
.catch((err) =>{
console.log(err)
res.render("index", {
weather: `That city is not avaible`
})
})
}
}
exports.renderAboutPAge = (req, res) => {
res.render("About")
}
I don't think its neccessary for this issue, but just incase here is my index.hbs file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Weather | Home</title>
<!-- Bootstrap core CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about">About</a>
</li>
</ul>
</div>
</nav>
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-12 text-center main">
<div>
<h1 class="mt-5">MVC Weather Finder</h1>
<p class="lead">Enter the name of the city and press search!</p>
</div>
<div>
<form action="/" method="post">
<input name="city" type="text">
<button>Go!</button>
</form>
<div class="mt-3">
{{weather}}
{{error}}
</div>
</div>
</div>
</div>
</div>
</body>
</html>
It turns out I was pulling data from my response object incorrectly and that was causing the issue.

Dropzone inside a html form with other form fields not working

I want to add a dropzone inside an existing form but it doesn't seem to work.
When I view the console I get error throw new Error("No URL provided"). When I click upload I get no preview either - all I get is a normal file input.
<link href="../dropzone.css" rel="stylesheet">
<form action="/" enctype="multipart/form-data" method="POST">
<input type="text" id ="Username" name ="Username" />
<div class="dropzone" id="my-dropzone" name="mainFileUploader">
<div class="fallback">
<input name="file" type="file" />
</div>
</div>
<div>
<button type="submit" id="submit"> upload </button>
</div>
</form>
<script src="../jquery.min.js"></script>
<script src="../dropzone.js"></script>
<script>
$("my-dropzone").dropzone({
url: "/file/upload",
paramName: "file"
});
</script>
No url provided error is because $("my-dropzone") is wrong instead it must be $('#mydropzone')
dropzone along with other form, yes this is very much possible, you have to post the data using the URL provided in the dropzone not in the form action. That means all your form data along with the files uploaded shall be posted back to the url provided for the dropzone. A simple untested solution is as below;
<link href="../dropzone.css" rel="stylesheet">
<form action="/" enctype="multipart/form-data" method="POST">
<input type="text" id ="Username" name ="Username" />
<div class="dropzone" id="my-dropzone" name="mainFileUploader">
<div id="previewDiv></div>
<div class="fallback">
<input name="file" type="file" />
</div>
</div>
<div>
<button type="submit" id="submitForm"> upload </button>
</div>
</form>
<script src="../jquery.min.js"></script>
<script src="../dropzone.js"></script>
<script>
$("#mydropzone").dropzone({
url: "/<controller>/action/" ,
autoProcessQueue: false,
uploadMultiple: true, //if you want more than a file to be uploaded
addRemoveLinks:true,
maxFiles: 10,
previewsContainer: '#previewDiv',
init: function () {
var submitButton = document.querySelector("#submitForm");
var wrapperThis = this;
submitButton.addEventListener("click", function () {
wrapperThis.processQueue();
});
this.on("addedfile", function (file) {
// Create the remove button
var removeButton = Dropzone.createElement("<button class="yourclass"> Remove File</button>");
// Listen to the click event
removeButton.addEventListener("click", function (e) {
// Make sure the button click doesn't submit the form:
e.preventDefault();
e.stopPropagation();
// Remove the file preview.
wrapperThis.removeFile(file);
});
file.previewElement.appendChild(removeButton);
});
// Also if you want to post any additional data, you can do it here
this.on('sending', function (data, xhr, formData) {
formData.append("PKId", $("#PKId").val());
});
this.on("maxfilesexceeded", function(file) {
alert('max files exceeded');
// handle max+1 file.
});
}
});
</script>
The script where you initialize dropzone can be inside $document.ready or wrap it as a function and call when you want to initialize it.
Happy coding!!

Password Protected Directory intermittent fail

I have a form on the only page within a directory that is password protected via cPanel. Such as...
www.site.com/directory/subdirectory/form.php
Once every twenty submits of the form (in the same session) I am redirected to:
www.site.com
and obviously the php form processing doesn't occur.
WHAT IS HAPPENING?
I have checked my redirects in cpanel and none are set. So I don-t even know why it goes to the index page!
NOTES
No question on SO mentions this problem and I have found nothing suitable in google. I'm not sure what the problem is so it's hard to 'google'.
Here is the form.php format
<?php
header('Content-Type: text/html; charset=utf-8');
session_start();
require 'functions.php';
connect();
/*“Æ” because UTF-8 encoding without BOM looks like ANSI*/
if(isset($_POST['newJob'])){
$jTDjobToDo = $_POST['jobToDo'];
$jTDwhenInfo = $_POST['whenInfo'];
$jTDwhenInfo = $jTDwhenInfo+ time();
$jTDinsertNewJob = $conn ->prepare ("INSERT INTO jobstodo (jobToDo,whenInfo) VALUES(:jobToDo,:whenInfo)");
$jTDinsertNewJob->bindParam(':jobToDo', $jTDjobToDo, PDO::PARAM_STR);
$jTDinsertNewJob->bindParam(':whenInfo', $jTDwhenInfo, PDO::PARAM_INT);
$jTDinsertNewJob->execute();
echo "New job added!<br/>";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>My page</title>
<LINK href="stylesheet.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="newjobform">
ADD A NEW JOB
<form action="http://www.site.com/myPage.php" method="POST">
New Job To Do <input type="text" name="jobToDo" id="newJobToDo" ><br/>
When to do<br/>
<input type="radio" name="whenInfo" value="0" CHECKED>Now /
<input type="radio" name="whenInfo" value="86400"> 1 day
/ <input type="radio" name="whenInfo" value="172800"> 2 days
/ <input type="radio" name="whenInfo" value="345600">4 days<br/>
<input type="radio" name="whenInfo" value="604800">7 days
/ <input type="radio" name="whenInfo" value="1209600">14 days
/ <input type="radio" name="whenInfo" value="2073600">24 days
/ <input type="radio" name="whenInfo" value="3888000">45 days<br/>
<input type="submit" value="ADD" name="newJob"><br/>
</form>
</div>
</body>
</html>
The function php connects as so..
try {
$conn = new PDO("mysql:host=$hostdb; dbname=$namedb", $userdb, $passdb);
//echo 'Connected to database';
}
catch(PDOException $e) {
echo $e->getMessage();
}
}

Model in Layout breaks other pages

I have a design flaw based on my lack of MVC4 experience.
The issue is that I have a model in my Layout...
#model BasicFinanceUI.Models.LoginModel
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/bootstrap.min.css")" rel="stylesheet"/>
<title>#ViewBag.Title</title>
</head>
The reason it's on my Layout, is that the Login button is on the layout screen, and it launches a modal popup, which has fiends that use the model.
So, at the bottom of the layout, I have:
<div class="modal fade" id="login" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3>Login</h3>
<div class="modal-body">
#using (Html.BeginForm("LoginUser", "User"))
{
<p>
#Html.LabelFor(x => x.Username)
#Html.TextBoxFor(x => x.Username)
</p>
<p>
#Html.LabelFor(x => x.Password)
#Html.PasswordFor(x => x.Password)
</p>
<p>
#Html.LabelFor(x => x.RememberMe)
#Html.CheckBoxFor(x => x.RememberMe)
</p>
<div class="modal-footer">
<input type="submit" value="Login" name="btn_login" class="btn btn-default" />
<a class="btn btn-primary" data-dismiss="modal">Cancel</a>
</div>
}
</div>
</div>
</div>
</div>
I also have a Login and Logout button on my /Home/Index, so the user see's two login buttons when on the default page. One on the main page, and one in the header/menu, which is shared.
I think having the model, and probably all the Login screen code, on the Layout page, might be the problem here. How should I be implementing this?
I need the Login button on the Index.cshtml page (Default), and the button in the Layout's menu at the top. And both use the model popup code shown above.
First build the view like you have it but instead of using helpers just build the html fields. Make sure you put an id or a class on the fields that we can use as a selector
<input type="text" class="txtUserName" /> etc
then make sure you have jquery referenced on the page and put this on the bottom of your screen
<script type="text/javascript">
$(document).ready(function(){
$('.btnSubmit').on('click', function(){
$.ajax({
url: "#(Url.Action("Action", "Controller")",
type: "POST",
contentType: "application/json",
data: { UserName: $('.txtUserName').val(), Password: $('.txtPassword').val() }
cache: false,
async: true,
success: function (result) {
alert('Login Successful!');
window.location = "#Url.Action("Index", "Controller")";
}
});
});
});
</script>
then on your controller you need to have a method set up to receive the ajax call
[HttpPost]
public ActionResult Login(string UserName, string Password){
//Check the user name and password against the database
//from here http://stackoverflow.com/questions/10608198/asp-net-mvc3-returning-success-jsonresult
var result=new { Success="True", Message="Success"};
return Json(result, JsonRequestBehavior.AllowGet);
}