问题
TL;DR
Form submits a POST request with "data/fileUpload".
Server responds 200 and renders a new page. Goody.
Try to upload a new file in the rendered page again.
POST request is now "data/fileUpload/fileUpload".
Server doesn't know what to do. Baddy.
I am not exactly sure what is going on, that's why the title is very vague. I am implementing a simple feature to a Node (Express) application. Here is what this feature does:
- User uploads a file.
- User submits the file for review.
- User receives a response.
Problem
Uploading a file and returning a result functionality works smoothly. After file is uploaded and the server renders a new page, browser is still at "data/fileUpload" url. Trying to upload a second file directs a POST request to the following url "data/fileUpload/fileUpload" which can not be routed by the server.
<!DOCTYPE html>
<!-- Boilerplate ... -->
<body
<div id="form">
<%= message %>
<% if(processed == "true"){ %>
<%= results %>
<% }; %>
<form method='post' action='data/fileUpload' enctype="multipart/form-data">
<input type='file' name='fileUploaded' id="browseButton" required>
<input type='submit' value="Upload" id="uploadButton">
</div>
<script>
var uploadField = document.getElementById("browseButton");
uploadField.onchange = function() {
if(this.files[0].size > 2097152){
alert("File is too big!");
this.value = "";
};
};
</script>
</body>
</html>
As you can see the form action is "data/fileUpload". This post request is handled by the following router and controllers.
// Defined in app.js
app.use('/data', dataRouter);
The following Router is in data.js. processController is imported from processData.js controller.
router.post('/fileUpload', [processController.fileUpload, processController.process]);
And this is the Controller for fileUpload and process.
exports.fileUpload = function(req, res,next) {
// Upload the file...
next(); // calls process function
};
// Process the data. Not implemented
exports.process = function(req, res) {
res.render('index', {processed:"true",
message: "hello", results:"result" });
});
};
The following is the incomplete directory tree.
├── app.js
├── controllers
│ └── processController.js
├── package.json
├── routes
│ ├── data.js
├── uploads
│ └── Uploaded.file
└── views
├── index.ejs
How can I enable server to go back to the initial page but also send results?
回答1:
You should use res.redirect()
combined with req.flash() - connect flash (that at some point got excluded from expressjs bundle) for what you are trying to do. (Which is sending an ok/not-ok message back to front).
res.render()
Sends back an html (or any other engine) template back to front and renders - It does not care for what happens next and this can cause problems such as yours (sending a full page as template and messing up data).
res.redirect()
redirects the user to another route (by this restarting the request like: GET /some_new_or_even_the_same_route
.
req.flash()
Can handle returned messages.
Also, with redirect()
you could send a status code as the first argument which can act as your processed true/false
I think res.render()
is just not the right function to use in your scenario.
来源:https://stackoverflow.com/questions/62750163/how-to-handle-an-incorrect-post-request-using-node-js