Replacing POST Form in WOPI by axios code in server-side - reactjs

I am trying to implement wopi protocol.
Using react, I have an iframe and a post-form which sets the content of iframe identified as collabora-online-viewer by requesting to address props.url with token props.token, as below (which works correctly):
useEffect(() => {
formElem.current.submit();
});
return (
<div style={{display: 'none'}}>
<form
ref={formElem}
action={props.url}
encType="multipart/form-data"
method="post"
target="collabora-online-viewer"
id="collabora-submit-form"
>
<input
name="access_token"
value={props.token}
type="hidden"
id="access-token"
/>
<input type="submit" value="" />
</form>
</div>
);
// my iframe in another component
<iframe
ref={iframeRef}
title="Collabora Online Viewer"
id="collabora-online-viewer"
name="collabora-online-viewer"
/>
Instead of sending this request by submitting a post-form, I need this request sent by my own express server using axios. How can i do this?
I have done as below, but it did not work:
//CLIENT SIDE
useEffect(() => {
sendRequest();
}, []);
async function sendRequest() {
const obj = {
url: props.url,
token: props.token
};
await axios
.post('/MyRequest', obj)
.then((res) => {
props.setIframeContent(res.data);
})
.catch((error) => {
console.log(error);
});
}
// my iframe in another component
const [iframeContent, setIframeContent] = useState('');
<iframe
srcDoc= {iframeContent}
ref={iframeRef}
title="Collabora Online Viewer"
id="collabora-online-viewer"
name="collabora-online-viewer"
/>
//SERVER SIDE
routeAuthenticated(
'POST',
'/MyRequest',
async (req, res) => {
try {
await axios
.post(req.body.url, req.body.token, {
// headers: {'Content-Type': 'multipart/form-data'}
})
.then((response) => {
res.send(response.data);
});
} catch (err) {
console.log(err);
}
}
);

Unfortunately it's not possible to post to Office Online Server with JavaScript. When an html form is submitted directly e.g.
<form action="https://someotherorigin.com">
Then no JavaScript is used, so CORS does not come into play when you post to OOS. But axios (or fetch or superagent etc.) use JavaScript, so CORS will block the request. See this SO post for more detail.

Related

Calling an Async function in React without clicking a button?

I'm working on a Spotify integration app, and I have the following code within the main function of the App. This code basically lets you log in through Spotify, and then upon being redirected to my app's page, you click a button that gets your top artists for a given time period from your Spotify data. I have included the code that I have a question about below:
***SOME CODE***
const getTopTracks = async (e) => {
e.preventDefault()
const {data} = await axios.get("https://api.spotify.com/v1/me/top/artists", {
headers: {
Authorization: `Bearer ${token}`
},
params: {
limit: 10,
time_range: "short_term"
}
})
console.log(data);
setArtists(data.items);
}
***SOME MORE CODE***
return (
<div className="App">
<header className="App-header">
<h1>monk<span className='smaller'>media</span>
</h1>
{!token ?
<a href={`${AUTH_ENDPOINT}?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=${RESPONSE_TYPE}&scope=${SCOPE}`}>Login to Spotify</a>
: <button className='logout' onClick={logout}> Logout </button>}
{token ?
<form onSubmit={getTopTracks}>
<input type="text" onChange={e => setSearchKey(e.target.value)}/>
<button type={"submit"}>GET MY TOP ARTISTS</button>
</form>
: <h2>Please login ^</h2>
}
{renderArtists()} //prints artists
</header>
</div>
);
}
I had followed a tutorial to create an app that allows you to search for artists through the Spotify Api, so I used some of that code here, which is why there is a form and a button to get your top artists. However, I'd like top artists to appear upon being redirected to my app after successfully logging in through Spotify, and I don't want there to be a button you have to push.
I tried removing the form, and just calling getTopTracks in the return statement, but then the Spotify Api call wouldn't work. I think it has something to do with the async function, but I'm not sure how to solve this problem. How can I remove the form and make it so the "getTopTracks" function is called immediately upon returning to my web app after logging in?
Any help would be appreciated!
You can call useEffect for this:
useEffect(() => {
const getTopTracks = async () => {
const { data } = await axios.get(
"https://api.spotify.com/v1/me/top/artists",
{
headers: {
Authorization: `Bearer ${token}`,
},
params: {
limit: 10,
time_range: "short_term",
},
}
);
console.log(data);
setArtists(data.items);
};
getTopTracks();
}, []);
I also highly recommend reading this article.

FormData not working with Axios Post request - MERN react Js

I've been trying to make a post request to my server(Node Js+Mongodb which runs on localhost too). Axios.post works properly on the client code, however when i try to use formData it doesn't. I can't seem to find any reason why it's not working.
It leaves no error on the console(which makes it more frustrating).
Here is the client code:
someone pls point me to what I might be doing wrong.
import React, { useState } from 'react'
import Axios from 'axios'
export default function InputData() {
const [inputName, setInputName] = useState("")
const [inputAge, setInputAge] = useState(0)
const [inputEmail, setInputEmail] = useState("")
const [userImage, setUserImage] = useState("")
const [info,setInfo] = useState("")
var bodyFormData = new FormData();
bodyFormData.append('name', inputName);
bodyFormData.append('age', inputAge);
bodyFormData.append("email", inputEmail)
const createUser = () => {
Axios.post("http://localhost:3008/createUser",
bodyFormData , { headers: { 'Content-Type': 'multipart/form-data' } }).then(function (response) {
//handle success
console.log(response);
}).catch(function (response) {
//handle error
console.log(response);
});
}
return (
<div>
<form onSubmit={createUser} encType="multipart/form-data">
<div>
<input type="text" placeholder='enter name' value={inputName} width={400} onChange={(e) => setInputName(e.target.value)} /><br/>
<input type="number" placeholder='enter age' width={400} value={inputAge} onChange={(e) => setInputAge(e.target.value)} /><br/>
<input type="email" placeholder='enter e-mail' width={400} value={inputEmail} onChange={(e) => setInputEmail(e.target.value)} /><br />
<button>Submit</button>
</div>
</form>
</div>
)
}
axios: "^0.27.2",
react: "^18.2.0"
Couple of points:
You're probably not seeing any errors (output) in the console because you're submitting the form. You can change your onSubmit handler to include preventDefault:
const createUser = (e) => {
Axios.post("http://localhost:3000/createUser", bodyFormData, { headers: { 'Content-Type': 'multipart/form-data' } })
.then(console.log)
.catch(console.error);
e.preventDefault();
}
You can also keep it as is and see the previous output by persisting the logs of your browse across requests, in Firefox this checkbox:
You should add method=post to your form
I think you will receive all the data from the event [createUser method] on submitting the form, Try removing the header If you still have problem try as below, If you still have the problem check the server side Post method Params
let data = { name: inputName, age: inputAge, email: inputEmail }
Axios.post("http://localhost:3008/createUser",data )
.then(function (response) { console.log(response); })
.catch(function (response) { console.log(response); });

how to send images through axios using gridfs?

how can i send a file/image in reactjs uploaded through an to the backend, using axios?
the simple input form is this :
<form className={classes.form} onSubmit={handleSubmit(submitFunc)}>
<Grid container spacing={2}>
<Grid item xs={12}>
<input
type="file"
accept="image/*"
alt="file"
name="file"
id="file"
/>
</Grid>
</Grid>
<Button
type="submit"
>
Add
</Button>
</form>
the submit function:
try {
await axios
.post(`http://localhost:5000/addPic`, data, {
headers: {
accept: "application/json",
"Accept-Language": "en-US,en;q=0.8",
"Content-Type": `multipart/form-data`,
},
})
}
);
} catch (error) {
console.log("error");
}
i tried this but it's not working, and i dont know why, because when i use postman to send an image to the same api, it works :
also when i use a view engine and use a form with method="POST" in the backend, it works!
here's the api code :
const conn = mongoose.createConnection(mongoURI);
let gfs;
conn.once("open", () => {
// Init stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("uploads");
});
let tempNameFile;
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads",
};
tempNameFile = filename;
console.log(tempNameFile);
resolve(fileInfo);
});
});
},
});
const upload = multer({ storage });
router.post("/", upload.single("file"), async (req, res) => {
console.log(tempNameFile);
res.send("good to go");
});
to sum up all of this, my question is how can i upload an image to the frontend using a simple input and send it through axios, the same way postman sends an image to the backend to be handled by gridfs and stored in the mongodb database
Since Postman worked, your backend is setup properly. Now on to your frontend.
Axios handles multipart form data if your data is an instance of FormData.
In your component you can set a state variable to hold the selected file
const [selectedFile, setSelectedFile] = useState(null);
Add an onInput to your <input /> field like so:
<input onInput={e => setSelectedFile(e.target.files[0])} />
In the submit function, wrap the file in a FormData and submit with Axios
try {
const data = new FormData();
data.append("file", selectedFile);
await axios.post(`http://localhost:5000/addPic`, data);
/* Do something if upload was successful */
} catch (error) {
console.log("error");
}

Sending an axios Post request with csv in its body

What i am trying to achieve is send a post request from my frontend to back end using axios.This post request has a csv file in its body.
Using postman : postman request
My code is this:
import React, { Component } from 'react';
import axios from 'axios'
class SessionsUpdate extends Component {
state = {
selectedFile: null
}
handleSubmit = async () => {
let formData = new FormData();
formData.append('file', this.state.selectedFile);
await axios.post(
'https://localhost:8765/...',
formData,
{ headers: { 'x-observatory-auth': localStorage.getItem("token"), 'Content-Type': 'multipart/form-data' } }
)
console.log("log") //this is not printed here
}
onFileChange = event => {
this.setState({ selectedFile: event.target.files[0] });
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<h1>Choose a file to store</h1>
</div>
<div>
<fieldset>
<input type="file" accept=".csv" onChange={this.onFileChange} />
</fieldset>
</div>
<input type="submit" value="Submit" />
</form>
);
}
}
export default SessionsUpdate;
So the HTML part creates a simple GUI to select a csv file from local storage and what i want is to pass this csv file to my post request.After searching online the main way i found to do this is by using formdata but it does not work on my case and i have been stuck in this for quite a while.This requests works fine on postman though.
Any ideas about what i am missing?

React axios post request does not send the data

I am using react for my app. I am learning post request. I found one dummy api site Mocky where I can test my post request. This is my api link .For post request I used axios. I don't know how the Mocky api works. I made post request. when I console log the input values I can the value.But when I console log the response it seems like it does not get the data. I don't see any where I am making mistake.
Here is my code:
import React, { useState } from 'react';
import { API_URLS } from '../utilities';
import axios from "axios";
export default function CreateAccount() {
const [state, setState] = useState({
"email": ``,
"password": ``,
"loading": false,
"error": ``
});
const onChangeStudent = (e) => {
setState({
...state,
[e.target.id]: e.target.value
});
};
const onSubmit = async (e) => {
e.preventDefault();
console.log(state);
const url = `https://run.mocky.io/v3/15c2b7ec-9f31-4a18-ae60-a7f41e1f39b2`;
const obj = {
"email": state.email,
"password": state.password
};
console.log(obj.email); //I can see the input value
console.log(obj.password);//I can see the input value
axios
.post(url, obj)
.then((res) => {
console.log(res.data); // it does not show the data
console.log(res);
})
.catch((error) => {
setState({
...state,
"error": error
});
});
};
return (
<div>
<form onSubmit={onSubmit}>
<input
type="text"
value={state.name}
onChange={onChangeStudent}
id="email"
required
/>
<input
type="password"
value={state.password}
onChange={onChangeStudent}
id="password"
required
/>
<button
className="btn waves-effect blue lighten-1"
type="submit"
name="action"
disabled={state.loading}
>
{state.loading ? `loading...` : `save`}
</button>
</form>
</div>
);
}
Hi can't seem to find anything wrong with what you are doing.
I tested the below and it worked for me. Try to change from .then to await. Hope this solves your problem. Check in your network tab if your request is successful and if you are sending the body.
try {
const response = await axios.post('https://run.mocky.io/v3/4b95050f-2bcc-4c78-b86e-6cac09372dce', data);
console.log("Response", response);
} catch(e) {
console.error(e);
}

Resources