Reputation: 105
My React component looks like:
import React from "react";
import { Form, FormGroup, FormText, Input, Label, Button } from "reactstrap";
import axios from "axios";
import ThankYouModal from "./ThankYouModal";
import Header from "./Header";
import Footer from "./Footer";
export default class Contact extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
message: "",
file: "",
submitted: false,
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.closeThankYouModal = this.closeThankYouModal.bind(this);
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
async handleSubmit(e) {
e.preventDefault();
const { name, email, message, file } = this.state;
this.setState({ submitted: true, message: "" });
e.target.message = "";
const formPDF = await axios.post("/api/formPDF", {
name,
email,
message,
file
})
}
Then within my render is:
<FormGroup>
<Label for="file">File</Label>
<Input
type="file"
name="file"
value={this.state.file}
onChange={this.handleChange} />
<FormText color="muted">
File must be sent as a PDF.
</FormText>
</FormGroup>
I then have nodemailer set up to post on "/api/formPDF" and I try to use req.body.file to pull the file name but Javascript does its job and converts the path to "C:\fakepath\MyPDFFile.pdf" and it says it can't find a file at that location.
I know my email setup is working because I can have it successfully send an email without an attachment, I am just having trouble getting a correct path name. I thought about streaming the data through node with fs, but I'm a bit at a loss on how to tell where fs to look and what the file name will be. Thanks in advance.
EDIT: Here is my nodemailer setup:
app.post("/api/formPDF", (req, res) => {nodemailer.createTestAccount((err, account) => {
const attach = fs.createReadStream("path", req.body.file);
const htmlEmail = `
<h3>Contact Details</h3>
<ul>
<li>Name: ${req.body.name}</li>
<li>Email: ${req.body.email}</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`
let transporter = nodemailer.createTransport({
name: *hidden*,
host: *hidden*,
port: 465,
secure: true,
auth: {
user: *hidden*,
pass: *hidden*
}
})
let mailOptions = {
from: *hidden*,
to: *hidden*,
replyTo: req.body.email,
subject: "New Message",
text: req.body.message,
html: htmlEmail,
attachments: [
{
path: attach
}
]
};
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return console.log(err)
}
})})});
Upvotes: 0
Views: 1660
Reputation: 347
A. Your not uploading the file look at the code at the bottom on how to upload a file with REACT and Axios. look at the onChange handler e.target.files[0], this is the file object that will be sent to the server. You don't only send a name.
B. Then you need to get that file on the Node server end doing something like this: https://gist.github.com/paambaati/db2df71d80f20c10857d
C. Then having the path to the file or files you uploaded and saved on the server side. Then you use it with NodeMailer.
import React from 'react'
import axios, { post } from 'axios';
class SimpleReactFileUpload extends React.Component {
constructor(props) {
super(props);
this.state ={
file:null
}
this.onFormSubmit = this.onFormSubmit.bind(this)
this.onChange = this.onChange.bind(this)
this.fileUpload = this.fileUpload.bind(this)
}
onFormSubmit(e){
e.preventDefault() // Stop form submit
this.fileUpload(this.state.file).then((response)=>{
console.log(response.data);
})
}
onChange(e) {
this.setState({file:e.target.files[0]})
}
fileUpload(file){
const url = 'http://example.com/file-upload';
const formData = new FormData();
formData.append('file',file)
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
return post(url, formData,config)
}
render() {
return (
<form onSubmit={this.onFormSubmit}>
<h1>File Upload</h1>
<input type="file" onChange={this.onChange} />
<button type="submit">Upload</button>
</form>
)
}
}
export default SimpleReactFileUpload
Upvotes: 1