I’m in the beginning stages of planning out my final Capstone project for my Bootcamp.
Two of the features I would like to include are the ability to upload:
Audio
Video
I will be using React.JS for Front-End and Python / Django for server side.
Any suggestions or recommendations for how to approach these upload features?
I’m currently beginning researching how to do this.
you can use html tag input on react
const [file , setFile] = useState();
<input
type="file"
id="fileInput"
onChange={(e) => setFile(e.target.files[0])}
/>
after that you can use FormData() to create file format then send file to api
const data = new FormData();
const filename = username + "_" + file.name;
data.append("name", filename);
data.append("file", file);
try {
api.uploadFile(data);
} catch (error) {
console.log(error);
}
at backend ( django ) I don't know how to handle file requset but you can find it easily . At react side you can use codes at top .
Related
I am using https://www.npmjs.com/package/convert-html-to-pdf to convert html to pdf in nodejs. I have a react frontend and nodejs backend. I want to convert the buffer to a file that people can download on the react side. How can I do this? I don't want to save the file on my servers.
We can set header Content-disposition attachment to indicate that the response is a downloadable file.
Backend: example in Express
const htmlToPDF = new HTMLToPDF(`
<div>Hello world</div>
`);
const buffer = await htmlToPDF.convert();
res.set("Content-Disposition", `attachment; filename="test.pdf"`);
res.set("Content-Type", "application/pdf");
res.send(buffer);
Frontend: example in React
const submit = () => {
window.open("http://localhost:8000"); // Your endpoint here
};
return (
<button onClick={submit}>Download</button>
);
If the endpoint is POST method then window.open won't work. We have to use a form:
<form action="http://localhost:8000" method="POST">
<button type="submit">Download</button>
</form>
I have an app using react and express on the backend and multer to manage the upload. The server side is running properly when I make tests using postman, but if trait to send an image from react the result is unexpected. In that case the file doesn't appear in the uploads folder, however with postman is immediatly.
UploadPage,jsx
const { register, handleSubmit } = useForm();
const onSubmit = async (data) => {
const formData = new FormData();
formData.append('petimage', data.petimage);
try {
const res = await axios.post('/api/petregister', formData);
console.log(res)
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
}
return (
<Container className="mt-5">
<Form onSubmit={handleSubmit(onSubmit)}>
<Form.Group controlId="formFile" className="mb-3">
<Form.Label>Imagen de tu Mascota</Form.Label>
<Form.Control type="file"
label="Select image"
name="petimage"
{...register("petimage")}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</Container>
Google Response
The fields with name petimage are the same that I expecified in the backend and used these in the postman tests.
Edit
const store = require('../middlewares/multer');
route.post('/petregister', store.array('petimage', 12), petregister);
The last section of code is the route that is linked with the multer midleware asigned to ssave the images.
When you are making a API call to the backend, it will upload the image to the specific folder that you are defining in the backend like :
const multer = require('multer');
const upload = multer({ dest: 'folder path' });
I think you are getting results unexpected because the name for the image you are giving in formData formData.append('petimage', data.petimage); i.e petimage, it should be the same in the multer fileupload method. You haven't shared the backend code. So, I'm hoping that it may be like this:
var fileUpload = upload.single('petimage'); when the name is the same it will work fine.
If the image is of big size, you can compress it. Please visit this link, it will help you for sure.
https://dev.to/franciscomendes10866/image-compression-with-node-js-4d7h
You can try:
Remove
formData.append('petimage', data.petimage);
and use instead
data.petimage.forEach(pet => formData.append("petimage", pet))
The solution was trait the image as an object. The code is the next:
Object.values(data.petimage).forEach(pet => formData.append('petimage', pet))
Then it worked as expected.
I would like to know the type of file obtained with req.files in NodeJS. I need this because the file uploaded has to be a photo for the well work of the app. It not only helps me to check that it is not a .jpg since you can make a .txt and change the extension.
The form is the following:
form(class="form add-form space-down" method="POST" enctype="multipart/form-data")
div.title
h1 UPLOAD NEW PROGRESS
div.form-group
label(for="weight") Weight:
input(type="number" name="weight" class="form-control" placeholder="Enter your weight")
div.form-group
label(for="front") Upload a front photo
input(type="file" name="front" accept="image/*")
div.form-group
label(for="from_side") Upload a from side photo
input(type="file" name="from_side" accept="image/*")
div.form-group
label(for="backwards") Upload a backwards photo
input(type="file" name="backwards" accept="image/*")
And the router handle is the following to obtain the photos uploaded:
routerProgress.post("/home/upload-progress", (req, res) => {
const front = req.files.front;
const from_side = req.files.from_side;
const backwards = req.files.backwards;
}
How can I be sure that front, from_side and backwards are photos?
If anyone has any idea how to do it, I would be very grateful if you could help me.
You can do something like this. Create a function which returns the extension of the file and you can check if it is a valid image extension or not.
routerProgress.post("/home/upload-progress", (req, res) => {
const front = getFileExtension(req.files.front);
const from_side = getFileExtension(req.files.from_side);
const backwards = getFileExtension(req.files.backwards);
if (front) {
// its an image, do something
}
}
function getFileExtension (filename) {
const allowedFileExt = ['JPEG', 'JPG', 'PNG', 'GIF', 'TIFF', 'PSD', 'PDF']; // you can add as per your requirement
const fileExt = /[^.]+$/.exec(filename);
return allowedFileExt.includes(fileExt[0].toUpperCase());
}
If that is the case, you should use mmmagic, it checks the content of the file instead checking only the extension. Try using this lib it will be more useful for your use case. Also, take a look at this npm package image-type
I am using Nodejs readStream.pipe(writeStream). How can I get the full path of the file I am uploading and assign it to createReadStream. I get only filename and When the file is in nodejs root directory it is fine no error but when I upload from anywhere else I get an error:
events.js:183
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open 'C:\Users\Esen\Documents\GitHub\gbmsturbo\nike.png'
I know that this happens because nike.png that I am uploading is not in "C:\Users\Esen\Documents\GitHub\gbmsturbo\".
It is inside this folder:
"C:\Users\Esen\Documents\GitHub\filestoupload"
I tried
function throwErrorDontCrash() {
process.on('uncaughtException', function (err) {
console.error(err.message)
})
}
and this prevents nodejs crash and uploads the file but with empty content (0 byte)
router.post('/upload', (req, res) => {
var filePath = req.body.file
var ext = path.extname(filePath)
var filename = path.basename(filePath, ext)
var newVerFilePath = "public/uploads/" + newVerFileName+ext
const readStream = fs.createReadStream(filePath)
throwErrorDontCrash()
const writeStream = fs.createWriteStream(newVerFilePath)
readStream.pipe(writeStream)
function throwErrorDontCrash() {
process.on('uncaughtException', function (err) {
//console.error(err.message)
})
}
and here is my form file
<form class="center" action="/upload" method="post">
<input id="file" type="file" name="file" required encrypt="multipart/form-data"/>
<input type="submit" value="UPLOAD">
I want filePath to include the directory path where ever the file is uploaded when user clicks on Choose or Browse button.
Currently, filePath gets only filename such as nike.png and my expectation is
to get "C:/Users/Esen/Documents/GitHub/filestoupload/nike.png"
it looks like you are writing an express app on nodejs. Your issue is here:
const readStream = fs.createReadStream(filePath);
I think that you believe this is how you "read" the file the user is uploading, but that's actually not possible - the "fs" module doesn't exist in the browser. The user navigating your website is uploading the image from their computer via a form, which means the image is coming in from the HTTP request (the req object), not from the file system.
(This can be confusing because in your case, you probably are running this express app locally on your machine, but it's easier to imagine it in production - the express app runs on a big server somewhere, and is a different computer than your user's computer, where the file being uploaded lives.)
Check out the related S.O. question How to upload, display and save images using node.js and express. Also, see the tutorial Upload Files or Images to Server using Nodejs.
I need to upload a file in react and send it to the Node backend.
Since I never worked with uploading and sending files before, this is a little troubling for me.
So far I found this:
// this creates a React component that can be used in other components or
// used directly on the page with React.renderComponent
var FileForm = React.createClass({
// since we are starting off without any data, there is no initial value
getInitialState: function() {
return {
data_uri: null,
};
},
// prevent form from submitting; we are going to capture the file contents
handleSubmit: function(e) {
e.preventDefault();
},
// when a file is passed to the input field, retrieve the contents as a
// base64-encoded data URI and save it to the component's state
handleFile: function(e) {
var self = this;
var reader = new FileReader();
var file = e.target.files[0];
reader.onload = function(upload) {
self.setState({
data_uri: upload.target.result,
});
}
reader.readAsDataURL(file);
},
// return the structure to display and bind the onChange, onSubmit handlers
render: function() {
// since JSX is case sensitive, be sure to use 'encType'
return (
<form onSubmit={this.handleSubmit} encType="multipart/form-data">
<input type="file" onChange={this.handleFile} />
</form>
);
},
});
Source: https://fitacular.com/blog/react/2014/06/23/react-file-upload-base64/
But now I basically just end up with some sort of string. But I need to send that file via REST to my Express backend, which needs to save that file in CouchDB.
What is the best/easiest way to accomplish that?
If you are using body-parser, know that it handles json and url encoded forms, not multipart data !
You should use an other module.
For more infos, give a look at : File uploading with Express 4.0: req.files undefined