Learning react by coding, here i want to let user choose an image then user shoul be able to send it as blob, need advice on converting it into blob ?
this is my fetch with post method
const sendToserver = async () => {
let pollUrl = `api/...`;
const blob: any = await getImage();
// SEND THE BLOB TO YOUR SERVER
try {
const res = await fetch(pollUrl, {
method: "POST",
body: blob,
});
const data = await res.text();
if (res.ok) console.log("SUCCESS", data);
else throw new Error(data);
} catch (e) {
console.error(e);
}}
my uploader which need advice on how to get blob image of it:
const {useState} = React;
const blobFile= (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
resolve(event.target.result)
};
reader.readAsDataURL(file);
})
const App = () => {
const [blob, setBlob] = useState('')
const onChange = (file) => {
if(!file) {
setBlob('');
return;
}
blobFile(file)
.then(dataUri => {
setBlob(dataUri)
})
}
return <div>
<img width="200" height="200" src={blob} alt="avatar"/>
<input type="file" onChange={(event) => onChange(event.target.files[0] || null)} />
</div>
}
ReactDOM.render(
<App/>,
document.getElementById('root')
);
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
english is not my mother language, so could be mistakes
CodePudding user response:
Unless you want to show this image to the user in the browser right after he sends it, you don't have to convert it to Blob in order to send to server, you can read this file and make a POST
directly to your api, so there in your api you can handle this file the way you want, like saving to disk or sending to some cloud service like aws bucket.
Anyway, I will show you both examples, how to convert to Blob and how to send to server.
converting to Blob
const onChange = (file) => {
if(!file) {
setBlob('');
return;
}
// just use the URL.createObjectURL to convert to blob
setBlob(URL.createObjectURL(file))
}
You should pay attention when converting files to Blob because it can leads to issues with memory, so when the Blob is no longer necessary for the user, you can remove it from memory this way:
URL.revokeObjectURL(blob)
sending the file to server
it's almost the same thing you've did before, but with the file directly set in the body
const sendToServer = async (file) => {
if(!file) return
try {
return await fetch('api/...', { method: 'POST', body: file }).then(res => {
console.log("SUCCESS", res.text())
})
} catch(error) {
console.log(error)
}
}
const App = () => {
return <div>
<img width="200" height="200" src={blob} alt="avatar"/>
<input type="file" onChange={async (event) => await sendToServer(event.target.files[0] || null)} />
</div>
}
Update: To use a button to send files you can make the input hidden and use the button to trigger the dialog box from the input, like so:
// I will be using the useRef hook, but you could do it with vanilla javascript as well
import React, { useRef} from 'react'
const App = () => {
const fileInputRef = useRef(null)
// this is the function that triggers the dialog box from the input
const openFileDialog = () => {
fileInputRef.current?.click()
}
return <div>
<img width="200" height="200" src={blob} alt="avatar"/>
// add hidden property and the ref to useRef hook
<input hidden ref={fileInputRef} type="file" onChange={async (event) => await sendToServer(event.target.files[0] || null)} />
// open the input's dialog on click
<button onClick={openFileDialog}> Upload file </button>
</div>
}