I want to upload a file as soon as it is added to input. I use code like this
<form>
<input id="MyInput" type="file">
</form>
<script>
$('#MyInput').fileupload({
url: '/Upload',
change: function() {
$('#MyInput').fileupload('send', {})
.success(function() { console.log('success') })
.error(function() { console.log('error') });
}
});
</script>
I see that jQuery-File-Upload send a request with files from the queue and server returns 200 OK. But the promise rejects and I have an 'error' in console.
I look inside the plugin code and see that in this case it returns a promise that always rejects. You should pass a fileInput or files as 'send' parameter to get a resolvable promise. But then files will be duplicated.
How can I get resolved promise with server response?
Related
I'm putting together a contact form using Svelte and SendGrid. Here is a basic app.svelte:
<script>
import sgMail from '#sendgrid/mail';
sgMail.setApiKey(import.meta.env.VITE_SENDGRID);
function submitForm() {
const msg = {
to: 'test#example.com',
from: 'test#example.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>'
};
console.log('Form submitted');
sgMail.send(msg);
}
</script>
<form on:submit|preventDefault={submitForm}>
<button type="submit">Submit</button>
</form>
The code above does not send an email after the user selects submit on the form, despite the function being called (it logs Form submitted in the console). When I move all code from submitForm() outside the function, the code executes on page load, so I know it's not an issue with my API key.
Any suggestions what I am missing?
Svelte is a frontend environment only. The Sendgrid package is desinged for a server side / node.js environment. In your example, your Sendgrid API key would be exposed because you're trying to use it on the frontend / client side.
A solution may be to look at SvelteKit, which has the concept of 'endpoints' which always run on the server side. Or you can create an express server to handle the sending of email to Sendgrid.
EDIT: The solution is to use Sveltekit endpoints. Endpoints always run on the server. Your final solution may look something like this:
File: /src/routes/api/sendmail.ts or /src/api/sendmail.js
import sgMail from "#sendgrid/mail";
sgMail.setApiKey(import.meta.env.VITE_SENDGRID);
export async function get(page) {
const msg = {
to: "test#example.com",
from: "test#example.com",
subject: "Sending with SendGrid is Fun",
text: "and easy to do anywhere, even with Node.js",
html: "<strong>and easy to do anywhere, even with Node.js</strong>",
};
console.log("Form submitted");
const output = await sgMail.send(msg);
return {
body: output,
};
}
File /src/routes/index.svelte
<script>
function submitForm() {
fetch("/api/sendmail");
}
</script>
<form on:submit|preventDefault={submitForm}>
<button type="submit">Submit</button>
</form>
hello I'm in the process of converting my HTTP website to https but after getting https to work no post request from forms work
I have looked around a lot but nothing really describes what I have going on here, I doubt it nginx because when I start burp suite and make the website server HTTP it sends a post request like usual, but when I run it on https the post request isn't even sent doesn't show anything on the burp suite logs
<form action="" method="post" autocomplete="off">
<p><input type="text" name=username id="username">:username
<p><input type="password" name=password id="password">:password
<p><input type="checkbox" name = "rmbm" id="rmbm">
<label for = "rmbm">remember me</label>
<p><input type=submit value=Login>
forgot password?
</form>
this is my form but I don't even see a post request
I should see a post request but I don't on burp sute
update:
hello, I've just had an epiphany. could it be the service worker and yes I was right after unregistering the service worker it worked perfectly so the problem is the service worker.
knowing this I will post the code
my service worker:
console.log('Hello from sw.js');
'use strict';
var cacheVersion = 1;
var currentCache = {
offline: 'offline-cache' + cacheVersion
};
this.addEventListener('install', event => {
event.waitUntil(
caches.open(currentCache.offline).then(function(cache) {
return cache.addAll([
'/static/html/offline.html',
'/sw.js'
]);
})
);
});
this.addEventListener('fetch', event => {
console.log("fetching");
if (event.request.mode === 'navigate' || (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
event.respondWith(
fetch(event.request.url).catch(error => {
// Return the offline page
return caches.match('/static/html/offline.html');
})
);
}
else{
event.respondWith(caches.match(event.request)
.then(function (response) {
return response || fetch(event.request);
})
);
}
});
now looking at my code it just dosnt handle post request
so i will try to fix this on my own
So I do want to say that I've been searching for the answer for this and I've also tried to console.log my req.body post form and I keep getting undefined. So I feel that I'm losing the data from the form I send, I'm not sure what I"m doing wrong. So time to show some code.
As a note: I am using Handlebars for my Express Setup.
app.js
var express = require('express'),
exphbr = require('express3-handlebars'), // "express3-handlebars"
nodemailer = require('nodemailer'),
helpers = require('./lib/helpers'),
app = express(), handlebars;
// Create `ExpressHandlebars` instance with a default layout.
handlebars = exphbr.create({
defaultLayout: 'main',
helpers : helpers,
extname : '.html',
// Uses multiple partials dirs, templates in "shared/templates/" are shared
// with the client-side of the app (see below).
partialsDir: [
'views/shared/',
'views/partials/'
]
});
// Register `hbs` as our view engine using its bound `engine()` function.
app.engine('html', handlebars.engine);
app.set('view engine', 'html');
require("./routes")(app, express, nodemailer);
app.listen(3000);
routes.js
module.exports = function (app, express, nodemailer) {
// set up the routes themselves
app.get('/', function (req, res) {
res.render('home', {
title: 'Larry King Orchestra'
});
});
// I cut out a majority of my routes to make this easier to read.
// SEND EMAIL FROM FORM
app.post('/', function (req, res) {
console.log("WTF");
console.log(req.body.name);
console.log(req.body.email);
var mailOpts, smtpTrans;
//Setup nodemailer transport, I chose gmail. Create an application-specific password to avoid problems.
smtpTrans = nodemailer.createTransport('SMTP', {
service: 'Gmail',
auth: {
user: "email#gmail.com",
pass: "password"
}
});
//Mail options
mailOpts = {
from: req.body.email, //grab form data from the request body object
to: 'anotheremail#gmail.com',
subject: 'LKO Contact Form',
html: 'From: ' + req.body.name + ' <' + req.body.email + '> <br>Phone: ' + req.body.tel + '<br>Date of Event: ' + req.body.date + '<br>Location: ' + req.body.location + '<br>Details & Comments:<br>' + req.body.message + '<br><br><p>Email form provided by WavaMedia.'
};
smtpTrans.sendMail(mailOpts, function (error, response) {
//Email not sent
if (error) {
res.render('home', {
title: 'Larry King Orchestra',
msg: 'Error occured, message not sent.',
err: true,
page: 'home'
});
}
//Yay!! Email sent
else {
res.render('home', {
title: 'Larry King Orchestra',
msg: 'Message sent! Thank you.',
err: false,
page: 'home'
});
}
});
});
// STATIC ROUTE FOR ASSESTS
app.use(express.static('assests/'));
};
I renamed the handlebars extension to be .html and I have the main layout using partials. SO app.get('/') will show this next file as a partial, and render it on the page.
contact.html
<form class="contact" action="/" method="post">
<label for="name">Name</label>
<input type="name" name="name" id="name">
<label for="email">Your Email (required)</label>
<input type="email" name="email" id="email">
<label for="tel">Phone Number</label>
<input type="tel" name="tel" id="tel">
<label for="date">Date of Your Event</label>
<input type="date" name="date" id="date">
<label for="location">Venue/Location</label>
<input type="location" name="location" id="location">
<label for-"message">Details & Comments</label>
<textarea name="message" id="message" rows="3"></textarea>
<input type="submit" name="submit" id="submit" value="Send" class="btn btn-default">
</form>
My Error:
TypeError: Cannot read property 'name' of undefined at c:\xampp\htdocs\lko\routes.js:129:26 at callbacks (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:164:37) at param (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:138:11) at pass (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:145:5) at Router._dispatch (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:173:5) at Object.router (c:\xampp\htdocs\lko\node_modules\express\lib\router\index.js:33:10) at next (c:\xampp\htdocs\lko\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.expressInit [as handle] (c:\xampp\htdocs\lko\node_modules\express\lib\middleware.js:30:5) at next (c:\xampp\htdocs\lko\node_modules\express\node_modules\connect\lib\proto.js:193:15) at Object.query [as handle] (c:\xampp\htdocs\lko\node_modules\express\node_modules\connect\lib\middleware\query.js:45:5)
So I'm not sure where I'm going wrong with the code. I believe the form is sending data to my node app, but where it's going, I'm not sure. I've setup the post method and so far no luck :( I have been trying for a couple days now. I have nodemailer installed as well. I've restarted the server, updated node and npm.
JavaScript Node Guru Masters, only you can show me the light! And thanks for reading though all of this, totally awesome!
app.use(express.bodyParser());
add that to your app.js
that's what grabs information from the post data form.
You have to require body parser package for this.
At first you have to install it with npm.
$ npm install --save body-parser
Then require that in your js file.
var bodyParser = require('body-parser');
Then add the parser. As you are using html post method it uses urlencoded as encoding type. For that add this line.
var urlencodedParser = bodyParser.urlencoded({ extended: false });
(If you use json you must use bodyParser.json() instead of this)
Now add the parser with the encoding type to app.post method as follows.
app.post('/',urlencodedParser, function (req, res) {
//your code here
});
You don't have to be explicitly mention any bodyParser or bodyParer.json
Instead You can make it simple to use this because this is a built-in middleware function in Express.
app.use(express.json());
app.use(bodyparser.urlencoded({extended : true }));
I've got a simply form, that sends POST data to my Node.JS server, with Express. This is the form:
<form method="post" action="/sendmessage">
<div class="ui-widget">
<input type="text" id="search" data-provide="typeahead" placeholder="Search..." />
</div>
<textarea id="message"></textarea>
</form>
The ui-widget and the input is releated with typehead, an autocomplete library from Twitter.
And this is how I handle the POST request in the server:
app.post('/sendmessage', function (req, res){
console.log(req.body);
usermodel.findOne({ user: req.session.user }, function (err, auser){
if (err) throw err;
usermodel.findOne({ user: req.body.search }, function (err, user){
if (err) throw err;
var message = new messagemodel({
fromuser: auser._id,
touser: user._id,
message: req.body.message,
status: false
});
message.save(function (err){
if (err) throw err;
res.redirect('/messages')
})
});
});
});
The console shows me '{}', and then an error with req.body.search, because search is not defined. I don't know what is happening here, and it's not a problem related with the typehead input. Any solution for this problem...?
Thank's advance!
req.body is made up of names and values.
add name="search" on your search box and try again.
You also must use the express/connect.bodyParser() middleware, thanks Nick Mitchinson!
I had this problem and it turned out I was using app.use(express.bodyParser()); but it was after the code I was using. Moving it up solved the issue.
on express 4 would be this one. (note that this will not parse multipart/uploads).
app.use(bodyParser.urlencoded({extended: true}));
and if you want to receive json input
app.use(bodyParser.json());
In my case it was caused by my app redirecting http to https.
Updating Facebook to use the https uri fixed it.
In my case I did not provide name tags like this name="firstname" in my input field. After adding them, everything worked.
Environment: JQuery Form Plugin, jQuery 1.7.1, Zend Framework 1.11.11.
Cannot figure out why jQuery won't parse my json object if I specify an url other than a php file.
The form is as follows:
<form id="imageform" enctype="multipart/form-data">
Upload your image <input type="file" name="photoimg" id="photoimg" />
<input type="submit" id ="button" value="Send" />
</form>
The javascript triggering the ajax request is:
<script type="text/javascript" >
$(document).ready(function() {
var options = {
type: "POST",
url: "<?php $this->baseURL();?>/contact/upload",
dataType: 'json',
success: function(result) {
console.log(result);
},
error: function(ob,errStr) {
console.log(ob);
alert('There was an error processing your request. Please try again. '+errStr);
}
};
$("#imageform").ajaxForm(options);
});
</script>
The code in my zend controller is:
class ContactController extends BaseController {
public function init() {
/* Initialize action controller here */
}
public function indexAction() {
}
public function uploadAction() {
if (isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST") {
$image = $_FILES['photoimg']['tmp_name'];
$im = new imagick($image);
$im->pingImage($image);
$im->readImage($image);
$im->thumbnailImage(75, null);
$im->writeImage('userImages/test/test_thumb.jpg');
$im->destroy();
echo json_encode(array("status" => "success", "message" => "posted successfully"));
}
else
echo json_encode(array("status" => "fail", "message" => "not posted successfully"));
}
}
When I create an upload.php file with the above code, and modify the url from the ajax request to
url: "upload.php",
i don't run into that parsing error, and the json object is properly returned. Any help to figure out what I'm doing wrong would be greatly appreciated! Thanks.
You need either to disable layouts, or using an action helper such as ContextSwitch or AjaxContext (even better).
First option:
$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->layout->disableLayout();
And for the second option, using AjaxContext, you should add in your _init() method:
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('upload', 'json')
->initContext();
This will disable automatically disable layouts and send a json header response.
So, instead of your two json_encode lines, you should write:
$this->status = "success";
$this->message = "posted successfully";
and
$this->status = "fail";
$this->message = "not posted successfully";
In order to set what to send back to the client, you simply have to assign whatever content you want into view variables, and these variables will be automatically convert to json (through Zend_Json).
Also, in order to tell your controller which action should be triggered, you need to add /format/json at the end of your URL in your jQuery script as follow:
url: "<?php $this->baseURL();?>/contact/upload/format/json",
More information about AjaxContext in the manual.
Is the Content-type header being properly set as "application/json" when returning your JSON?