Uploading multiple content to Cloudinary React js - reactjs

I'm building this website where users can sometimes upload one audio or one image and sometimes both at the same time to cloudinary. I'm able to upload from the front-end (react.js) one or the other (image or audio) but not both at the same time.
I saw this post that says that it is not possible except if we "write a script and use multi-threads (up to 10 threads) to upload many files at once. " I have no idea what it means in the context of react.js | JavaScript.
My code is the following:
I first call the handleUploadCloudinary with its parameter. The function is being called once the data is ready to be published.
const publishTheEntry = () => {
const {
mainText,
mediaAudio,
mediaImg
} = formData;
if(mediaAudio !== ""){
handleUploadCloudinary("audio");
};
if(mediaImg !== ""){
handleUploadCloudinary("image");
};
};
The handleUploadCloudinary() is the following:
const handleUploadCloudinary = (mediaType) => {
const {
mediaAudio,
mediaImg
} = formData;
const formDataCloudinary = new FormData();
formDataCloudinary.append("upload_preset", my_var_here);
formDataCloudinary.append("timestamp", (Date.now() / 1000) | 0);
if(mediaType === "img"){
formDataCloudinary.append("file", mediaImg);
axios.post(
"https://api.cloudinary.com/v1_1/sismographie-cloud/image/upload",
formDataCloudinary
).then((response) => {
console.log(response);
let url = response.data.secure_url;
setFormData({...formData, mediaImg: url});
})
}else if(mediaType === "audio"){
formDataCloudinary.append("file", mediaAudio);
axios.post(
"https://api.cloudinary.com/v1_1/sismographie-cloud/upload",
formDataCloudinary
).then((response) => {
let url = response.data.secure_url;
setFormData({...formData, mediaAudio: url});
})
}
};
Even if, for when both audio + image are stored into the state, I can console.log() both of the conditions, the state won't bot update the formData with both. One will successfully sate the state with a new cloudinary link while the other one will remain a buffer.

You can loop through your resources list and upload assets one by one, or create new threads at the backend (best practice).
This link is a demo for uploading multiple files using Axios and React:
https://codesandbox.io/s/chunked-client-side-upload-forked-vqx6mp?file=/src/CldCustUploadLgRestApi.js

Related

Firebase Storage async request with "listAll" method. React

I'm getting an image from a user and storing it with in Cloud Storage through Firebase. The storing works fine.
Right after that I'm requesting all images from the storage to display them, but I got the response without the last submit. So I need to refresh the page, then useEffect make one more request and everything works.
UPD. Here's the the complete logic:
This function is uploading image to the storage:
const uploadImage = async (image,imageName) => {
if (image == null) return;
const imageRef = ref(storage,`images/${imageName}`);
try {
uploadBytes(imageRef, image);
} catch (err) {
alert(`${err}`)
}
}
This function does request to firestore, but doesn't return last uploaded image every time, just randomly. sometimes it does, usually not :
const getImages = async () => {
try {
const imagesListData = await listAll(imagesListRef);
setImagesList([]);
imagesListData.items.forEach(item => {
getDownloadURL(item).then(url => setImagesList(prev => [...prev,url]));
})
} catch(err){
alert(err.message);
}
}
after refreshing the page, useEffect does the job :
useEffect(() => {
getImages();
},[])
As I said above sometimes it works as I expected from the first try without me changing the code(which is the most confusing),most of the times I need to refresh the page to get the last image.
p.s. list() instead listAll() give same results

Axios post request with formData

I want to make a form with multiple input (two text and one image).
Furthermore, I'm using react, axios, formik and I submit my data to strapi.
With only one text and one file, it works fine, but when I try to add a new append, I've got the error
When using multipart/form-data you need to provide your data in a JSON 'data' field.
const onSubmit = async (event) => {
const data = new FormData()
//This works
data.append('data', JSON.stringify({title:event.title}))
data.append('files.cover', file)
//This doesnt
data.append('title', JSON.stringify({title:event.title}))
data.append('description', JSON.stringify({description:event.description}))
data.append('files.cover', file)
try{
const response = await axios.post('http://localhost:1337/foodtrucks', data,
{
headers: userToken && { Authorization: `Bearer ${userToken}` }
},
)
// const data = await response.json()
console.log("response", response)
} catch(err){
// setError(err.response.data.message[0].messages[0].message)
setError("error")
console.log(err)
}
}
I tried to add headers, to use form-data, etc. Nothing works.
I think axios is meant for calling APIs - it may not be easy (or possible to send form data).
If you're running in the Browser, you may want to use plain XMLHttpRequest. I came across this article, which defines the submitForm function. It has helped me a lot on many projects.

Express + React | Googleapis - download a file

Im so new on React components and I try to download files from my google drive folder, after a long time currently I have working my API to upload, and get files. My question is, how should I pass the data to download the file on my front end?
How can I get the files from my google drive, and download on react component?
Thanks in advance, and sorry for my explication, I dont know what I currently doing with the file.
Note: This code is just as example to download an image, I want to pass a fileID to download anything, pdfs, docs, png, etc.
Update: After triying differents solutions my api function was completed like this:
google_Ctrl.getDownload = async(req, res) => {
console.log(req.params);
let Google = await drive.files.get(
{fileId: req.params.id,
alt: 'media'},
{ responseType: 'stream' }
).then((request) => {
console.log(request);
fileType = request.headers['content-type'];
fileName = ( "file" + '.' + fileType );
fileData = request.data;
res.set(request.headers)
// res.set("Content-Type", fileType);
// res.set("Content-Disposition", "attachment; filename='archivo.png'");
fileData.pipe(res)
});
}
My function its currently working, when I using api.rest to send a GET Request they provide me my files. But now my problem is on React Component, I read a lot of posts but I did not found the solution, I currently using downloadjs trying this solution, unsuccessfully.
const DownloadFile = () => {
axios.get(process.env.REACT_APP_API_URL + 'google/download/' + "1YtDWD9hNEgCUi8YGQPjV98sULhyM5m8C")
.then((res) => {
console.log(res);
// res.blob()
// fileDownload(res.data, 'filename.png');
download(res.data, "file.png", res.headers['content-type']);
}).catch((error) =>{
console.error(error);
message.error('upload failed.');
});
}
This is my download function on React component, my .txt files works, but when I try to download pdf's, docs, xlsx, etc, dosent work, what can I do?
With Api.rest I tested my api function and it's working, I can download my files from api.rest, but my react functions apparently its badly formatted, I guess.
Okey, after a long time checking the code I found my error on the React Function, if someone is in the same position, here the code working:
API Google:
google_Ctrl.getDownload = async(req, res) => {
console.log(req.params);
console.log(req.body);
let Google = await drive.files.get(
{fileId: req.params.id,
alt: 'media'},
{ responseType: 'stream' }
).then((request) => {
console.log(request);
fileType = request.headers['content-type'];
fileName = ( "file" + '.' + fileType );
fileData = request.data;
// res.set(request.headers)
console.log(fileType);
res.set("Content-Type", fileType);
res.set("Content-Disposition", "attachment; filename='archivo.png'");
fileData.pipe(res)
});
}
React Component:
const DownloadFile = () => {
axios.get(process.env.REACT_APP_API_URL + 'google/download/' + "1YtDWD9hNEgCUi8YGQPjV98sULhyM5m8C",
{responseType: 'blob'})
.then((res) => {
console.log(res);
// res.blob()
fileDownload(res.data, 'filename.png');
// download(res.data, "file.pdf", res.headers['content-type']);
}).catch((error) =>{
console.error(error);
message.error('upload failed.');
});
}
The next step is send the FileID, Filename with the extention and when you recive use that name/extension to save correctly the file :D.

React onSubmit e.preventDefault() not working sometimes + Axios

Right now I'm facing this strange problem in React where the onSubmit function with e.preventDefault() does avoid refreshing the page sometimes, and sometimes it doesn't.
I've created two hooks to keep track of the uploaded files and their progress bars.
const [ uploadedFiles, setUploadedFiles ] = useState([]);
const [ uploadPercentages, setUploadPercentages ] = useState([]);
The onSubmit function uses Axios to make a request to the backend.
const onSubmit = async e => {
e.preventDefault();
if(!!file) {
// Show file box on screen
let index = addUpload(file);
const formData = new FormData();
formData.append("file", file);
try {
await axios.post("/upload_video", formData, {
onUploadProgress: progressEvent => {
const { loaded, total } = progressEvent;
let progress = uploadPercentages.concat(0)
progress[index] = Math.round((loaded * 100) / total)
setUploadPercentages(progress);
}
})
} catch(err) {
// Handlers
}
}
return false // trying something different to avoid refresh
}
Just in case, the addUpload function has shown little to no relation with the source of the problem. I took it away to test it and things behave the same way.
If anyone can help I would appreciate it.
Edit:
Here is the form.
<form className="choose-file" onSubmit={onSubmit}>
<div className="file-container">
{ file ?
<p> { file.name } </p>
:
<label className="file-label" htmlFor="customFile">
<input type="file" className="file-input" id="customFile" onChange={ onChange }/>
<p><i className="fas fa-cloud-upload-alt"></i></p>
<p>Click here to select file</p>
</label>
}
</div>
<div className="file-options">
<input type="submit" value="Upload" className="file-input" id="customFile"/>
<button type="button" onClick={ removeFile }>Delete</button>
</div>
</form>
"file" is a third hook just to show the user the name of the file they just selected.
Edit 2:
The problems seems to appear only when file sizes are greater than 100MB. Besides, once the problem shows up, it starts to happen to every single file no matter its size.
For instance if I upload a 7MB file, page does not refresh, if I then try a 100MB file it starts refreshing for every upcoming file and all console logs after the axios post are never seen again.
Edit 3:
Since I'm running a local backend on Flask, I tried disconnecting it from the React app to see what happens. For small files the request to the backend is only asked once and the alarm inside the catch(err) triggers. For big files the request is asked around four times and it never reaches the catch part.
Send help
I guess the problem in not with addUpload but with the async. You can try this way
const onSubmit = (e) => {
e.preventDefault();
// After collecting formData ...
// in the *try* block do this
const post = axios.post("/upload_video", formData, {
onUploadProgress: progressEvent => {
const { loaded, total } = progressEvent;
let progress = uploadPercentages.concat(0)
progress[index] = Math.round((loaded * 100) / total)
setUploadPercentages(progress);
}
post.then(() => {alert('Done posting')}) // inside this you can do whatever you want to do after axios.post
}
**EDIT : **
Since you mentioned in the comment that the solution does not work, here's an alternative.
Declare a new function
const async post = () => {
// Get the formData here
await axios.post("/upload_video", formData, {
onUploadProgress: progressEvent => {
const { loaded, total } = progressEvent;
let progress = uploadPercentages.concat(0)
progress[index] = Math.round((loaded * 100) / total)
setUploadPercentages(progress);
}
}
// Now in the onSubmit function
const onSubmit = (e) => {
e.preventDefalut();
post()
}
This is the final solution I have. Hope this works...
I've been facing problems with using arrow functions as HANDLERS,
try turning it into normal function
async function HandelOnSubmit (e) {
e.preventDefault();
if(!!file) {
// Show file box on screen
let index = addUpload(file);
const formData = new FormData();
formData.append("file", file);
try {
await axios.post("/upload_video", formData, {
onUploadProgress: progressEvent => {
const { loaded, total } = progressEvent;
let progress = uploadPercentages.concat(0)
progress[index] = Math.round((loaded * 100) / total)
setUploadPercentages(progress);
}
})
} catch(err) {
// Handlers
}
}
return false // trying something different to avoid refresh }
At the end, the problem turned out to be something as simple as saving the files in the React's public folder.
My guess is that this caused the whole project to refresh every time a change is detected inside this folder. For small objects the time it takes almost zero, but for big files it takes a while, causing the components to refresh as well.

Value of state variable is lost - React

I want to build a CRUD in React with Laravel and Firebase. Everything is perfect when I'm working with text, but I got trouble when I try to upload an image to Firebase Storage. I can save it but I can't get its URL.
I wrote 2 "console.log". In the first one the URL is there, but the second one (when I try to get the URL from the state variable) doesn't return anything.
handleSubmit = event =>{
event.preventDefault();
const {imagen} = this.state;
if(imagen!=null){
const uploadTask = storage.ref(`imagenes/${imagen.name}`).put(imagen);
uploadTask.on('state_changed',
(snapshot) => {
const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100);
this.setState({progress});
},
(error) => {
console.log(error);
},
() => {
storage.ref('imagenes').child(imagen.name).getDownloadURL().then(url => {
this.setState({url});
console.log(this.state.url); //<<<<<<<<<<<<<SHOW URL (IT'S OK!)
})
});
}
var direccion = null;
const form = event.target;
let data = new FormData(form);
data.append('url', this.state.url);
console.log(this.state.url); //<<<<<<<DOESN'T SHOW URL !! (HERE'S THE TROUBLE)
If you want to check the entire file:
https://github.com/AndresVasquezPUCE/project/blob/master/pelicula
I'm not a professional, so please don't be rude :D
this.setState is asynchronous
If you want to get the updated state value, add a callback and access the new state there like
this.setState({ url: 'some url'}, () => {
conosle.log(this.state.url);
});
Data is loaded from Firebase asynchronously. By the time your console.log(this.state.url); //<<<<<<<DOESN'T SHOW URL !! (HERE'S THE TROUBLE) the data hasn't been loaded from Firebase yet, and the then hasn't been called yet.
Any code that needs the data from Firebase needs to either be inside the then() callback (such as console.log(this.state.url); //<<<<<<<<<<<<<SHOW URL (IT'S OK!)) or be called from there (such as this.setState({url})).

Resources