How to upload image to specific collection with reactjs? - reactjs

I am trying to upload an image to specific collection and wrote a function to send post request to nodejs server but it is not working properly. Well when i upload by postman it is working fine but the logic that i wrote in front end seems not working. Here is the code :
const [image, setImage] = useState(null);
const [isCollectionCreated, setIsCollectionCreated] = useState(false);
const postImage= async () => {
const data = await response.json()
if (image) {
const fd = new FormData();
console.log("FD",fd);
fd.append("image", image);
await fetch(
`https://itransition-capstone.herokuapp.com/collections/${data._id}`,
{
method: "POST",
body: fd,
headers: {
"Authorization": "Bearer " + token,
},
}
);
alert("Image uploaded");
}
}
};
return (
<Form>
<Form.Group>
<Form.Label>Upload an image</Form.Label>
<Form.Control
type="file"
alt="file-upload"
value={requestData.image}
onChange={(event) => {
console.log(event.target.files);
setImage(event.target.files[0]);
}}
/>
</Form.Group>
<Button
variant="success"
type="submit"
className="mt-3 rounded-pill"
onClick={postImage}
>
Submit
</Button>
</Form>
)

Related

How can we add react js pdf file in firebase realtime database

I am trying to add reactjs pdf file in real time database but my file is not added in firebase. I am shared my code please anyone can help me to solve this issue
my code
import React, { useState } from 'react'
function Demo() {
const [file, setFile] = React.useState("");
function handleUpload(event) {
setFile(event.target.files[0]);
}
const postData = async (e) => {
e.preventDefault();
const result = await fetch('------/data.json', {
method: "POST",
headers: {
"Content-Type": "application/json",
}, body: JSON.stringify({
file
})
})
if (result) {
setFile({file:''})
alert("message send successfull...")
}
} else {
alert("please fill data")
}
}
)
return (
<div>
<div id="upload-box">
<input type="file" onChange={handleUpload} />
<p>Filename: {file.name}</p>
</div>
<button type="button" onClick={postData} className="btn btn-warning" > Submit feedback </button>
</div>
)

Can't send files using Redux Form

I'm creating a webpage for me and I'm working with Redux/Redux Form. My backend is working fine, but I can't figure out how to work on my front-end. I'm not using any library to fetch the image in my front, I just copy and pasted a FieldFileInput and it's working fine.
Here is my PostForm.tsx:
renderInput = ({input, label, meta}: {input: any, label: any, meta: any}) => {
const className = `field ${meta.error && meta.touched} ? 'error' : ''`;
return (
<div className={className}>
<label>{label}</label>
<div className="input-group input-group-lg">
<input className="form-control"{...input} autoComplete="off"/>
</div>
{this.renderError(meta)}
</div>
)
};
onSubmit = (formValues: any) => {
//#ts-ignore
this.props.onSubmit(formValues)
};
render() {
return (
<form
onSubmit={ this.props.handleSubmit(this.onSubmit)}
className="ui form error"
>
<div className="create-post-field-two">
<Field
name="title"
component={this.renderInput}
label="Enter Title"
/>
</div>
<div className="create-post-field-two">
<Field
name="body"
component={this.renderInput}
label="Enter Description"
/>
</div>
<div className="create-post-field-two">
<Field
name="imageUrl"
component={FieldFileInput}
label="Enter Image"
/>
</div>
<div className="postButton">
<button className="btn btn-outline-secondary">Submit</button>
</div>
</form>
)
}
}
In this page I'm certain that everything works correctly, because I receive all data in my Action.
Here is my Redux Action
export const createPost = ( formValues: any) => async(dispatch: any, getState: any) => {
const { userId } = getState().auth;
let token = userId
const headers = {
// 'Content-Type': 'multipart/form-data',
authorization: `Bearer ${token}`,
};
let formData = new FormData();
formData.append('imageUrl', formValues.imageUrl);
try {
const response = await AlleSys.post('/posts', {...formValues, image: formData}, {headers})
dispatch({type: CREATE_POST, payload: response.data})
history.push('/')
}catch (err) {
console.log("ERROR: Couldn't post for identified user");
}
};
If I uncomment the Content-Type I receive the error Error: Multipart: Boundary not found
in my Back-End.
Here Is a screenshot of my request using insomnia.
I'm stuck on this for days and I can't figure out how to achieve the file upload in the front-end. Please don't mind the typings, I'll correct later.
I used bodyFormData.append to my form fields in the Redux Action and worked like a charm.
export const createPost = ( formValues: any) => async(dispatch: any, getState: any) => {
const { userId } = getState().auth;
let token = userId
const headers = {
authorization: `Bearer ${token}`,
Accept: 'application/json',
};
const { title, body, image } = formValues;
const bodyFormData = new FormData();
bodyFormData.append('title', title);
bodyFormData.append('body', body);
bodyFormData.append('image', image);
try {
const response = await AlleSys.post('/posts', bodyFormData, {headers})
console.log(response)
dispatch({type: CREATE_POST, payload: response.data})
history.push('/')

Mulitple image add in react js

I am working on a project where I have one page where you should be able to add images. One by one it's worked perfectly. Now I want to make to be able to multiple add and upload. I don't want to use any library for image upload.
const onFileChange = (e) => {
const reader = new FileReader();
reader.onload = () => {
if (reader.readyState === 2) {
setPreview(reader.result);
}
};
reader.readAsDataURL(e.target.files[0]);
if (e.target.files[0]) {
setOver(true);
}
const copy = [...image];
copy.push(e.target.files[0]);
setImage([...copy]);
};
const onFileUpload = () => {
const formdata = new FormData();
image.forEach((elem) => {
formdata.append("data", elem);
});
formdata.append("id_grobnog_mjesta", Id);
addImage(formdata);
};
const addImage = async (data) => {
try {
setIsLoading(true);
const response = await apiRequest({
method: "post",
url: `spisak-srebrenica/upload`,
headers: {
Authorization: `Bearer ${token}`,
},
data,
});
if (response.data.success) {
getVictimImage();
}
setIsLoading(false);
setImage([]);
} catch (err) {
setIsLoading(false);
setImage([]);
}
};
Upload component :
<Upload>
<BiImageAdd size={50} opacity={0.5} />
<input type="file" onChange={onFileChange} />
<div className="items">
<p>Dodajte sliku</p>
<span className="format">PNG,JPG,GIF do 10MB</span>
</div>
</Upload>
add multiple attribute
<input type="file" id="files" name="files" multiple>
https://www.w3schools.com/tags/att_input_multiple.asp

Image upload in mern stack using multer not working

I'm trying to upload image in MongoDB using multer and react but I'm unable to post it. I have three inputs in by form i.e title, content and image. If I try to post title and content only it is successfully being posted. I have also added "proxy": "http://localhost:8000", in frontend package.json file
Here is my form
function PostCreate() {
const [title, setTile] = useState("");
const [content, setContent] = useState("");
const [image, setImage] = useState({});
const dispatch = useDispatch();
const post = useSelector((state) => state.postReducer);
const fileOnChange = (e) => {
setImage(e.target.files[0]);
};
const submitPost = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("image", image);
dispatch(createPost(title, content, image));
};
return (
<div className="postCreate">
<h3 className="postCreate__heading">Create New Post</h3>
<div className="formBody">
<form onSubmit={submitPost}>
<div className="formInputs">
<label className="label">Title</label>
<input
className="titleInput"
type="text"
value={title}
onChange={(e) => setTile(e.target.value)}
placeholder="Enter the Title of the Post"
/>
</div>
<div className="formInputs">
<input type="file" onChange={fileOnChange} />
</div>
<div className="formInputs">
<label className="label">Content</label>
<textarea
className="titleInput"
type="text"
style={{
width: "1500px",
height: "500px",
color: "black",
outline: "none",
border: "none",
borderRadius: "6px",
}}
value={content}
onChange={(e) => setContent(e.target.value)}
/>
</div>
<div className="button">
<Button type="submit" variant="contained" color="primary">
Post
</Button>
</div>
{/* <button type="submit">Post</button> */}
</form>
Here is my action
export const createPost = (title, content, image) => async (dispatch) => {
try {
dispatch({ type: POST_POST_LOADING });
const config = { headers: { "Content-Type": "application/json" } };
const { data } = await axios.post(
"/api/newpost",
{ title, content },
config
);
dispatch({
type: POST_POST_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: POST_POST_FAIL,
payload: error,
});
}
};
Here is my postController
const createPost = async (req, res) => {
const { title, content, writer, comment, image } = req.body;
const fileType = req.file.mimetype.split("/")[1];
const newFileName = req.file.filename + "." + fileType;
fs.rename(
`uploads/images/${req.file.filename}`,
`uploads/images/${newFileName}`,
(req, res) => {
console.log("Renamed");
}
);
// const imageUrl = req.file.filename;
const newPost = await Post.create({
title,
content,
writer,
comment,
image,
// imageUrl,
});
if (newPost) {
res.send("Post created");
console.log("Post created");
} else {
res.status(201).send("Post not created");
console.log("Post not created");
}
};
Here is my routes
router.post("/newpost", upload.single("image"), createPost);
You're creating a form, which is a good start, but not sending it with axios.
To send a file from frontend to backend, you need to construct a form using FormData API and append the file to it. You can also append additional data to it.
Here is how I would change your code to work. In your form file:
const formData = new FormData();
formData.append('image', image);
formData.append('title', title);
formData.append('content', content);
dispatch(createPost(formData));
Then change your action to:
export const createPost = (formData) => async (dispatch) => {
try {
dispatch({ type: POST_POST_LOADING });
const config = { headers: { "Content-Type": "multipart/form-data" } };
const { data } = await axios.post(
"/api/newpost",
formData,
config
);
dispatch({
type: POST_POST_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: POST_POST_FAIL,
payload: error,
});
}
};

Cloudinary return empty url on first try

It is strange that whenever I restart the ReactJS and click on postDetails, it always returns an empty URL, and if I click again it returns the URL path of the image. Am I missing something in this code here. many thanks in advance and greatly appreciated.
const Addpost = () => {
const [photo, setPhoto] = useState("")
const [photoURL, setPhotoURL] = useState("")
const postDetails = () => {
const data = new FormData()
data.append("file", photo)
data.append("upload_preset", "xxxxx")
data.append("cloud_name", "xxxxx")
fetch("https://api.cloudinary.com/v1_1/xxxxx/image/upload",{
method: "POST",
body: data
})
.then(res => res.json())
.then((data) => {
setPhotoURL(data.url)
})
.catch(err => {
console.log(err)
})
}
return (
<React.Fragment>
<input
type="file"
className="form-control-file"
id="photo"
name="photo"
onChange={(e) => setPhoto(e.target.files[0])}
/>
<button
type="submit"
className="btn btn-primary btn-block"
onClick={postDetails}
>
Submit
</button>
</React.Fragment>
)
}
try to do async await then (setPhotoUrl() will only be updated once the fetch get something or console.log('No data fetched!')):-
const postDetails = async() => {
const data = new FormData()
data.append("file", photo)
data.append("upload_preset", "xxxxx")
data.append("cloud_name", "xxxxx")
let res = await fetch("https://api.cloudinary.com/v1_1/xxxxx/image/upload",{
method: "POST",
body: data
})
if(!res) console.log('No data fetched!')
let data = res.json()
setPhotoURL(data.url)
}

Resources