upload image file from react to nodejs - node.js

This is react code
import React, { Component } from "react";
import Webcam from "react-webcam";
import * as faceapi from "face-api.js";
import { browserHistory } from "react-router";
import axios from "axios";
export default class WebCamPicure extends Component {
constructor() {
super();
this.state = {
selectedFile: null
};
fileSelectedHandler = (event) => {
console.log(event.target.files[0]);
this.setState({
selectedFile: event.target.files[0]
});
};
fileUploadHandler = () => {
const fd = new FormData();
fd.append("image", this.state.selectedFile, this.state.selectedFile.name);
fetch("http://localhost:5000/upload", {
method: "POST",
headers: { "Content-Type": "multipart/form-data" },
mode: "no-cors",
body: fd
});
};
render() {
return (
<div
className="App"
style={{
display: "flex",
flexDirection: "column",
alignItems: "center"
}}
>
<div class="upload">
<input type="file" onChange={this.fileSelectedHandler} />
<button onClick={this.fileUploadHandler}>upload</button>
</div>
</div>
);
}
}
this is node server code
const express = require("express");
var mysql = require("mysql");
const axios = require("axios");
var connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "expression_detection"
});
connection.connect((err) => {
if (!!err) {
console.log("error");
} else {
console.log("connected");
}
});
const app = express();
app.get("/api/customers", (req, res) => {
const customer = [
{ id: 1, firstname: "jhon", lastname: "doe" },
{ id: 2, firstname: "praveen", lastname: "smith" },
{ id: 3, firstname: "kumar", lastname: "swason" }
];
res.json(customer);
});
app.get("/", (req, res) => {
connection.query("SELECT * FROM individual_result", (error, row, fields) => {
if (!!error) {
console.log("Error in the query");
} else {
console.log("seccessful query");
console.log(row);
}
});
res.json("hello");
});
app.post("/upload", (req, file, res) => {
console.log("got it");
console.log(req);
// console.log(res);
});
const port = 5000;
app.listen(port, () => {
console.log("server started on port " + port);
});
I am trying upload image to nodejs server but i not able to recevie the upload file in server.I uploaded my code above please help me to solve this.now i need to get the uploaded file in server and store in database
I am trying upload image to nodejs server but i not able to recevie the upload file in server.I uploaded my code above please help me to solve this.now i need to get the uploaded file in server and store in database

You will need to configure a dedicated handler to work with multipart/form-data.
You can use multer.
Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files.

Related

how to Connect React Native component with Node js Server? (React Native, NodeJS(without Express), MongoDB)

I'm creating a simple React Native app, using...(React Native as FrontEnd, Node js as Server(without Express Framework) Database in MongoDB Local), so I Created Backend for the app, Server.js and React Native component in CreateUser.js
my problem is
When I click submit button for store data that time I got an Error and it was TypeError(Network Request Failed), I tried to call API with different IP Addresses also,
so please help me to how can I connect React Native with NodeJS,
CreateUser.js (frontEnd)
import React from 'react';
import { StyleSheet,
Text,
View,
TextInput,
TouchableOpacity
} from 'react-native';
class CreateUser extends React.Component {
constructor(){
super();
this.state ={
name:'',
email:'',
mobile:''
}
}
updateValue(text, field){
if(field == 'name'){
this.setState({
name:text,
})
}
else if(field == 'email'){
this.setState({
email:text,
})
}
else if(field == 'mobile'){
this.setState({
mobile:text
})
}
console.log(text);
}
submit(){
let collection = {}
collection.name=this.state.name,
collection.email=this.state.email,
collection.mobile=this.state.mobile
console.warn(collection);
console.log("submit btn pressed and collection is", collection);
// fetch code
var url = 'http://localhost:3005/save';
console.log("collections is that ===== ",collection)
fetch('url', {
method: 'post',
headers:{
'Content-Type': 'application/json',
'Accept':'application/json'
},
body: JSON.stringify(collection),
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(res => console.log('Success',res))
}
render(){
const {name, email, mobile} = this.state
return (
<View style={styles.container}>
<Text style={styles.header}>Insert User</Text>
<TextInput
placeholder="Enter Name"
style={styles.textinput}
onChangeText={(text) => this.updateValue(text, 'name')}
></TextInput>
<TextInput
placeholder="Enter Email"
style={styles.textinput}
onChangeText={(text) => this.updateValue(text, 'email')}
></TextInput>
<TextInput
placeholder="Enter Mobile"
style={styles.textinput}
onChangeText={(text) => this.updateValue(text, 'mobile')}
></TextInput>
<TouchableOpacity
style={styles.btn}
onPress={() => this.submit()}
>
<Text >Submit</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
regform:{
alignSelf:'stretch',
},
header:{
fontSize:24,
color:'#000',
paddingBottom:10,
marginBottom:20,
borderBottomColor:'#199187',
borderBottomWidth:1,
},
textinput:{
alignItems:'stretch',
height:40,
marginVertical:10,
marginHorizontal:10,
marginBottom:20,
color:'black',
borderBottomColor:'gray',
borderBottomWidth:2,
},
btn:{
alignSelf:'stretch',
alignItems:'center',
backgroundColor:'#59cbbd',
padding:20,
marginTop:30,
},
btntext:{
color:'#000',
fontWeight:'bold',
},
});
export default CreateUser;
server.js (backEnd)
// http module Node server
const { json } = require("body-parser");
const http = require("http");
const { parse } = require('querystring');
const app = http.createServer((req,res) =>{
const url = require('url');
const bodyParser = require('body-parser')
const mongoose = require('mongoose');
const User = require('./User');
var jsonParser = bodyParser.json();
const path = req.url;
console.log(req.url);
if(req.url ==="/save" && req.method == 'POST' ){
console.log("inside save API ") ;
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', () => {
console.log(
parse(body)
);
res.end(body);
});
var MongoClient = require('mongodb').MongoClient;
var urlm = "mongodb://localhost:27017/userdb";
MongoClient.connect(urlm, function(err, db) {
if (err) throw err;
var dbo = db.db("userdb");
var jsonObj = JSON.parse(body);
var myobj = {body};
console.log("Post Data BODY is ",jsonObj);
dbo.collection("users").insertOne(jsonObj, function(err, res) {
if (err) throw err;
console.log("1 record inserted");
db.close();
});
});
}
}).listen(3005,()=>{
console.log('server is running on 3005 port');
});
The url parameter in the fetch function in your react native code is variable not a string, its url not 'url'
fetch(url, {
method: 'post',
headers:{
'Content-Type': 'application/json',
'Accept':'application/json'
},
body: JSON.stringify(collection),
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(res => console.log('Success',res))
}

Network error from using localhost when web app is launched with Netlify

I just deployed a Spotify web app with Netlify. It works fine when it's running on my computer but it doesn't work on others. It shows Network Error, POST http://localhost:4000/search_result net::ERR_CONNECTION_REFUSED. I changed the url of the axios request to "/search_result" but it still didn't work. How should I fix it?
Here's my code.
Main.js
import React, { Component } from "react";
import SingerBox from "./SingerBox";
import axios from "axios";
import "../../App.css";
export class Main extends Component {
constructor(props) {
super(props);
this.state = {
keyword: "",
artists: [],
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({ keyword: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.keyword === "") {
alert("Enter Search Keyword");
}
axios
.post(
"/search_result",
{
keyword: this.state.keyword,
},
{
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
}
)
.then((res) => {
this.setState({ artists: res.data });
})
.catch((err) => {
console.log(err);
});
}
render() {
return (
<div className="container">
<div className="main">
<form onSubmit={this.handleSubmit}>
<label className="header" htmlFor="search">
Explore New Artists
</label>
<span>
<input
className="search-box"
type="search"
value={this.state.keyword}
onChange={this.handleChange}
name="keyword"
placeholder="Search artists..."
/>
<button className="submit-btn" type="submit" value="Submit">
Search
</button>
</span>
</form>
<br />
{this.state.artists.map((elem) => (
<SingerBox images={elem.images} name={elem.name} id={elem.id} />
))}
<br />
</div>
</div>
);
}
}
export default Main;
server.js
const express = require("express");
const SpotifyWebApi = require("spotify-web-api-node");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const port = 4000 || process.env.PORT;
require("dotenv").config();
app.use(express.json());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
// Create the api object with the credentials
var spotifyApi = new SpotifyWebApi({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
});
// Retrieve an access token.
function newToken() {
spotifyApi.clientCredentialsGrant().then(
function (data) {
console.log("The access token expires in " + data.body["expires_in"]);
// Save the access token so that it's used in future calls
spotifyApi.setAccessToken(data.body["access_token"]);
},
function (err) {
console.log("Something went wrong when retrieving an access token", err);
}
);
}
newToken();
tokenRefreshInterval = setInterval(newToken, 1000 * 60 * 60);
app.post("/search_result", (req, res) => {
spotifyApi
.searchArtists(req.body.keyword)
.then(function (data) {
let search_res = data.body.artists.items;
res.json(search_res);
res.end();
})
.catch((err) => {
console.log(err);
res.status(500).send(err);
});
});
app.get("/albums/:id", (req, res) => {
console.log(req.params.id);
spotifyApi
.getArtistAlbums(req.params.id, { limit: 40 })
.then(function (data) {
res.json(data.body.items);
res.end();
});
});
app.get("/albums/tracks/:albumID", (req, res) => {
console.log(req.params.albumID);
spotifyApi
.getAlbumTracks(req.params.albumID, { limit: 20 })
.then(function (data) {
console.log(data.body);
res.json(data.body.items);
res.end();
});
});
app.listen(port, () => console.log(`It's running on port ${port}`));
It is likely that the server code isn't running as you expect it to.
Think about what commands you run to get that localhost server running on your machine, compared to the build command you provided o Netlify to build your site.
Netlify is primarily for hosting static sites, so will not automatically provide a backend server for you to use.
You can either host the server part of your app on something like Heroku (and then have to hard-code the URL of that server instance into your app), or you can use Netlify Functions to handle your basic post request, which will let you use the relative URLs as in your question.

Why is my website running fine on my computer but not on other's?

I made a Spotify web app and launched it with Netlify. When I run its server file, it works well on my computer but not on my friend's. I thought it was because of the Spotify API at first but another web app I made, which doesn't use any API, only works on my computer as well. I think it's because of the server port or something but I'm not sure how to fix it.
Here's the website url and the server side code.
https://xenodochial-kepler-118793.netlify.app
server.js
const express = require("express");
const SpotifyWebApi = require("spotify-web-api-node");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const port = 4000 || process.env.PORT;
require("dotenv").config();
app.use(express.json());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
// Create the api object with the credentials
var spotifyApi = new SpotifyWebApi({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
});
// Retrieve an access token.
function newToken() {
spotifyApi.clientCredentialsGrant().then(
function (data) {
console.log("The access token expires in " + data.body["expires_in"]);
// Save the access token so that it's used in future calls
spotifyApi.setAccessToken(data.body["access_token"]);
},
function (err) {
console.log("Something went wrong when retrieving an access token", err);
}
);
}
newToken();
tokenRefreshInterval = setInterval(newToken, 1000 * 60 * 60);
app.post("/search_result", (req, res) => {
spotifyApi
.searchArtists(req.body.keyword)
.then(function (data) {
let search_res = data.body.artists.items;
res.json(search_res);
res.end();
})
.catch((err) => {
console.log(err);
res.status(500).send(err);
});
});
app.get("/albums/:id", (req, res) => {
console.log(req.params.id);
spotifyApi
.getArtistAlbums(req.params.id, { limit: 40 })
.then(function (data) {
res.json(data.body.items);
res.end();
});
});
app.get("/albums/tracks/:albumID", (req, res) => {
console.log(req.params.albumID);
spotifyApi
.getAlbumTracks(req.params.albumID, { limit: 20 })
.then(function (data) {
console.log(data.body);
res.json(data.body.items);
res.end();
});
});
app.listen(port, () => console.log(`It's running on port ${port}`));
Main.js
import React, { Component } from "react";
import SingerBox from "./SingerBox";
import axios from "axios";
import "../../App.css";
export class Main extends Component {
constructor(props) {
super(props);
this.state = {
keyword: "",
artists: [],
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({ keyword: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.keyword === "") {
alert("Enter Search Keyword");
}
axios
.post(
"/search_result",
{
keyword: this.state.keyword,
},
{
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
}
)
.then((res) => {
this.setState({ artists: res.data });
})
.catch((err) => {
console.log(err);
});
}
render() {
return (
<div className="container">
<div className="main">
<form onSubmit={this.handleSubmit}>
<label className="header" htmlFor="search">
Explore New Artists
</label>
<span>
<input
className="search-box"
type="search"
value={this.state.keyword}
onChange={this.handleChange}
name="keyword"
placeholder="Search artists..."
/>
<button className="submit-btn" type="submit" value="Submit">
Search
</button>
</span>
</form>
<br />
{this.state.artists.map((elem) => (
<SingerBox images={elem.images} name={elem.name} id={elem.id} />
))}
<br />
</div>
</div>
);
}
}
export default Main;
You have hardcoded localhost in your code somewhere. The apis are hitting your local server when someone is searching for the artist.
Remove localhost from code and every thing should work fine.

ReactNative : variable for FormData() being logged as undefined in ReactNative application when i make an http request with a file

i have been trying to make a post request from my react native app on an android emulator but the object that i am sending in the body of the request is being vvalued as undefined,been trying alot to solve this issue but no success. Please help me
here is the code to my form in the app known as "API.js" its named so just for testing the API endpoints
import React, { Component } from "react";
import {
Text,
TextInput,
View,
TouchableHighlight,
StyleSheet,
Button,
FormData
} from "react-native";
import Permissions from "react-native-permissions";
import ImagePicker from "react-native-image-crop-picker";
import axios from "axios";
var styles = StyleSheet.create({});
var msg = "Select Image";
var data;
export default class API extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
price: "",
size: "",
description: "",
image: "",
popularity: ""
};
}
FormDataFunc() {
let form = new FormData();
form.append("name", this.state.name);
form.append("price", this.state.price);
form.append("size", this.state.size);
form.append("description", this.state.description);
form.append("image", this.state.image);
form.append("popularity", this.state.popularity);
return form;
return form;
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
Submit() {
axios({
method: "post",
url: "http://192.168.0.102:3000/products",
data: this.FormDataFunc,
headers: {
Accept: "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
body: this.FormDataFunc
})
.then(() => {
console.log("DONE!");
this.props.navigation.navigate("offersScreen");
})
.catch(err => {
console.log(err);
console.log(this.FormDataFunc);
});
}
componentDidMount() {
Permissions.check("photo").then(response => {
// Response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
console.log(response);
});
}
render() {
const image = () => {
ImagePicker.openPicker({
multiple: false,
includeBase64: true
}).then(images => {
console.log(images);
this.setState({
images: { data: `\`${images.mime}\`;base64,\`${images.data}\`` }
});
console.log(this.state.images);
msg = "Selected";
});
};
return (
<View>
<TextInput placeholder="Name" name="name" />
<TextInput placeholder="Price" name="price" />
<TextInput placeholder="Size" name="size" />
<TextInput placeholder="Description" name="description" />
<TouchableHighlight onPress={image} name="image">
<Text>{msg}</Text>
</TouchableHighlight>
<TextInput placeholder="Popularity" name="popularity" />
<TouchableHighlight title="Submit" onPress={this.Submit}>
<Text>Send</Text>
</TouchableHighlight>
</View>
);
}
}
here is the code to my backend route "product.js" which recieves the request(node.js and express)
const express = require("express");
const router = express.Router();
const bodyParser = require("body-parser");
const path = require("path");
const cloudinary = require("cloudinary");
const mongoose = require("mongoose");
//Product Model
const product = require("../models/product").product;
router.use(bodyParser.json());
//GET route
router.get("/", (req, res) => {
product.find().then(product => res.json(product));
});
// POST route
cloudinary.config({
cloud_name: "cloud222",
api_key: "783935981748815",
api_secret: "uY47vBS1rI2x5jvFtnXQIjMMqU0"
});
router.post("/", (req, res) => {
//MISC//
let imageUrl;
console.log("starting");
//MISC//
//CLOUDINARY UPLOAD
cloudinary.v2.uploader.upload(req.body.image, (error, result) => {
if (error) {
console.log(error);
console.log(`${req.body.image}`);
} else {
imageUrl = result.secure_url;
//MONGO UPLOAD
var productv = {
name: req.body.name,
price: req.body.price,
size: req.body.size,
description: req.body.description,
image: imageUrl,
popularity: req.body.popularity
};
const productvar = new product(productv);
productvar
.save()
.then(product => console.log(product))
.then(product => res.json(product))
.catch(err => console.log(err));
}
});
//END//
});
module.exports = router;
the data is being logged as undefined and therefore the request doesnt get a response
I think the problem is that you have created a FormData and wanted to post it, but the headers you added is "application/json". You should change it:
headers: {
'content-type': 'multipart/form-data',
'Accept':'multipart/form-data',
},
Hope it works for you.
Problem solved
Had to use onChangeText = instead of onChange as onChange does not return a string

Upload image file from React front end to Node/Express/Mongoose/MongoDB back end (not working)

I’ve spent most of a day looking into this and trying to make it work. This is an app with a React/Redux front end, and a Node/Express/Mongoose/MongoDB back end.
I currently have a Topics system where an authorized user can follow/unfollow topics, and an admin can Add/Remove topics.
I want to be able to upload an image file when submitting a new topic, and I want to use Cloudinary to store the image and then save the images path to the DB with the topic name.
The problem I am having is that I am unable to receive the uploaded file on the back end from the front end. I end up receiving an empty object, despite tons of research and trial/error. I haven’t finished setting up Cloudinary file upload, but I need to receive the file on the back end before even worrying about that.
SERVER SIDE
index.js:
const express = require("express");
const http = require("http");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const app = express();
const router = require("./router");
const mongoose = require("mongoose");
const cors = require("cors");
const fileUpload = require("express-fileupload");
const config = require("./config");
const multer = require("multer");
const cloudinary = require("cloudinary");
const cloudinaryStorage = require("multer-storage-cloudinary");
app.use(fileUpload());
//file storage setup
cloudinary.config({
cloud_name: "niksauce",
api_key: config.cloudinaryAPIKey,
api_secret: config.cloudinaryAPISecret
});
const storage = cloudinaryStorage({
cloudinary: cloudinary,
folder: "images",
allowedFormats: ["jpg", "png"],
transformation: [{ width: 500, height: 500, crop: "limit" }] //optional, from a demo
});
const parser = multer({ storage: storage });
//DB setup
mongoose.Promise = global.Promise;
mongoose.connect(
`mongodb://path/to/mlab`,
{ useNewUrlParser: true }
);
mongoose.connection
.once("open", () => console.log("Connected to MongoLab instance."))
.on("error", error => console.log("Error connecting to MongoLab:", error));
//App setup
app.use(morgan("combined"));
app.use(bodyParser.json({ type: "*/*" }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
router(app, parser);
//Server setup
const port = process.env.PORT || 3090;
const server = http.createServer(app);
server.listen(port);
console.log("server listening on port: ", port);
TopicController/CreateTopic
exports.createTopic = function(req, res, next) {
console.log("REQUEST: ", req.body); //{ name: 'Topic with Image', image: {} }
console.log("IMAGE FILE MAYBE? ", req.file); //undefined
console.log("IMAGE FILES MAYBE? ", req.files); //undefined
const topic = new Topic(req.body);
if (req.file) {
topic.image.url = req.file.url;
topic.image.id = req.file.publid_id;
} else {
console.log("NO FILE UPLOADED");
}
topic.save().then(result => {
res.status(201).send(topic);
});
};
router.js
module.exports = function(app, parser) {
//User
app.post("/signin", requireSignin, Authentication.signin);
app.post("/signup", Authentication.signup);
//Topic
app.get("/topics", Topic.fetchTopics);
app.post("/topics/newTopic", parser.single("image"), Topic.createTopic);
app.post("/topics/removeTopic", Topic.removeTopic);
app.post("/topics/followTopic", Topic.followTopic);
app.post("/topics/unfollowTopic", Topic.unfollowTopic);
};
CLIENT SIDE
Topics.js:
import React, { Component } from "react";
import { connect } from "react-redux";
import { Loader, Grid, Button, Icon, Form } from "semantic-ui-react";
import {
fetchTopics,
followTopic,
unfollowTopic,
createTopic,
removeTopic
} from "../actions";
import requireAuth from "./hoc/requireAuth";
import Background1 from "../assets/images/summer.jpg";
import Background2 from "../assets/images/winter.jpg";
const compare = (arr1, arr2) => {
let inBoth = [];
arr1.forEach(e1 =>
arr2.forEach(e2 => {
if (e1 === e2) {
inBoth.push(e1);
}
})
);
return inBoth;
};
class Topics extends Component {
constructor(props) {
super(props);
this.props.fetchTopics();
this.state = {
newTopic: "",
selectedFile: null,
error: ""
};
}
onFollowClick = topicId => {
const { id } = this.props.user;
this.props.followTopic(id, topicId);
};
onUnfollowClick = topicId => {
const { id } = this.props.user;
this.props.unfollowTopic(id, topicId);
};
handleSelectedFile = e => {
console.log(e.target.files[0]);
this.setState({
selectedFile: e.target.files[0]
});
};
createTopicSubmit = e => {
e.preventDefault();
const { newTopic, selectedFile } = this.state;
this.props.createTopic(newTopic.trim(), selectedFile);
this.setState({
newTopic: "",
selectedFile: null
});
};
removeTopicSubmit = topicId => {
this.props.removeTopic(topicId);
};
renderTopics = () => {
const { topics, user } = this.props;
const followedTopics =
topics &&
user &&
compare(topics.map(topic => topic._id), user.followedTopics);
console.log(topics);
return topics.map((topic, i) => {
return (
<Grid.Column className="topic-container" key={topic._id}>
<div
className="topic-image"
style={{
background:
i % 2 === 0 ? `url(${Background1})` : `url(${Background2})`,
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundSize: "cover"
}}
/>
<p className="topic-name">{topic.name}</p>
<div className="topic-follow-btn">
{followedTopics.includes(topic._id) ? (
<Button
icon
color="olive"
onClick={() => this.onUnfollowClick(topic._id)}
>
Unfollow
<Icon color="red" name="heart" />
</Button>
) : (
<Button
icon
color="teal"
onClick={() => this.onFollowClick(topic._id)}
>
Follow
<Icon color="red" name="heart outline" />
</Button>
)}
{/* Should put a warning safety catch on initial click, as to not accidentally delete an important topic */}
{user.isAdmin ? (
<Button
icon
color="red"
onClick={() => this.removeTopicSubmit(topic._id)}
>
<Icon color="black" name="trash" />
</Button>
) : null}
</div>
</Grid.Column>
);
});
};
render() {
const { loading, user } = this.props;
if (loading) {
return (
<Loader active inline="centered">
Loading
</Loader>
);
}
return (
<div>
<h1>Topics</h1>
{user && user.isAdmin ? (
<div>
<h3>Create a New Topic</h3>
<Form
onSubmit={this.createTopicSubmit}
encType="multipart/form-data"
>
<Form.Field>
<input
value={this.state.newTopic}
onChange={e => this.setState({ newTopic: e.target.value })}
placeholder="Create New Topic"
/>
</Form.Field>
<Form.Field>
<label>Upload an Image</label>
<input
type="file"
name="image"
onChange={this.handleSelectedFile}
/>
</Form.Field>
<Button type="submit">Create Topic</Button>
</Form>
</div>
) : null}
<Grid centered>{this.renderTopics()}</Grid>
</div>
);
}
}
const mapStateToProps = state => {
const { loading, topics } = state.topics;
const { user } = state.auth;
return { loading, topics, user };
};
export default requireAuth(
connect(
mapStateToProps,
{ fetchTopics, followTopic, unfollowTopic, createTopic, removeTopic }
)(Topics)
);
TopicActions/createTopic:
export const createTopic = (topicName, imageFile) => {
console.log("IMAGE IN ACTIONS: ", imageFile); //this is still here
// const data = new FormData();
// data.append("image", imageFile);
// data.append("name", topicName);
const data = {
image: imageFile,
name: topicName
};
console.log("DATA TO SEND: ", data); //still shows image file
return dispatch => {
// const config = { headers: { "Content-Type": "multipart/form-data" } };
// ^ this fixes nothing, only makes the problem worse
axios.post(CREATE_NEW_TOPIC, data).then(res => {
dispatch({
type: CREATE_TOPIC,
payload: res.data
});
});
};
};
When I send it like this, I receive the following on the back end:
(these are server console.logs)
REQUEST: { image: {}, name: 'NEW TOPIC' }
IMAGE FILE MAYBE? undefined
IMAGE FILES MAYBE? undefined
NO FILE UPLOADED
If I go the new FormData() route, FormData is an empty object, and I get this server error:
POST http://localhost:3090/topics/newTopic net::ERR_EMPTY_RESPONSE
export const createTopic = (topicName, imageFile) => {
console.log("IMAGE IN ACTIONS: ", imageFile);
const data = new FormData();
data.append("image", imageFile);
data.append("name", topicName);
// const data = {
// image: imageFile,
// name: topicName
// };
console.log("DATA TO SEND: ", data); // shows FormData {} (empty object, nothing in it)
return dispatch => {
// const config = { headers: { "Content-Type": "multipart/form-data" } };
// ^ this fixes nothing, only makes the problem worse
axios.post(CREATE_NEW_TOPIC, data).then(res => {
dispatch({
type: CREATE_TOPIC,
payload: res.data
});
});
};
};
Solution was to switch to using Firebase instead, and deal with image upload on the React client (this was attempted with cloudinary but with no success). The resulting download url can be saved to the database with the topic name (which is all I wanted from cloudinary) and now it is displaying the correct images along with the topics.

Resources