英文:
How can I save an image on the server as a URL?
问题
I removed app.use(fileUpload());
. So it finally worked.
But unfortunately in the folder images
of the backend
I only get these files c43jnfeh734hdfudf
.
For this reason, nothing is displayed in the frontend.
我移除了 `app.use(fileUpload());`。所以它最终成功了。
但不幸的是,在`backend`的`images`文件夹中,我只得到了这些文件`c43jnfeh734hdfudf`。
因此,前端什么都没有显示。
I have a problem. I would like to save images with a fixed URL on my server.
I found the following code snippet, but unfortunately it doesn't work.
I get the following error in the backend: 'TypeError: Cannot read property 'path' of undefined'.
The following values are 'undefined'. const imagePath = req.file.path
const description = req.body.description
How can I save an image as a URL on the server?
Here is the tutorial, where I found the code snippet https://github.com/meech-ward/sammeechward.com_mdx/blob/master/content/articles/uploading-images-express-and-react/index.mdx
React
我有一个问题。我想在我的服务器上以固定的URL保存图像。
我找到了以下代码片段,但不幸的是它不起作用。
在后端我得到以下错误:'TypeError: Cannot read property 'path' of undefined'。
以下值为'undefined'。 `const imagePath = req.file.path` `const description = req.body.description`
我怎样才能将图像保存为服务器上的URL?
这是我找到代码片段的教程链接 https://github.com/meech-ward/sammeechward.com_mdx/blob/master/content/articles/uploading-images-express-and-react/index.mdx
**React**
```js
import { useState } from 'react'
import axios from 'axios'
export default function App() {
const [file, setFile] = useState()
const [description, setDescription] = useState("")
const [image, setImage] = useState()
const submit = async event => {
event.preventDefault()
const formData = new FormData()
formData.append("image", file)
formData.append("description", description)
const result = await axios.post('/api/images', formData, { headers: {'Content-Type': 'multipart/form-data'}})
setImage(result.data.imagePath)
}
return (
<div className="App">
<form onSubmit={submit}>
<input
filename={file}
onChange={e => setFile(e.target.files[0])}
type="file"
accept="image/*"
></input>
<input
onChange={e => setDescription(e.target.value)}
type="text"
></input>
<button type="submit">Submit</button>
</form>
{ image && <img src={image}/>}
</div>
)
}
Backend
import { useState } from 'react'
import axios from 'axios'
export default function App() {
const [file, setFile] = useState()
const [description, setDescription] = useState("")
const [image, setImage] = useState()
const submit = async event => {
event.preventDefault()
const formData = new FormData()
formData.append("image", file)
formData.append("description", description)
const result = await axios.post('/api/images', formData, { headers: {'Content-Type': 'multipart/form-data'}})
setImage(result.data.imagePath)
}
return (
<div className="App">
<form onSubmit={submit}>
<input
filename={file}
onChange={e => setFile(e.target.files[0])}
type="file"
accept="image/*"
></input>
<input
onChange={e => setDescription(e.target.value)}
type="text"
></input>
<button type="submit">Submit</button>
</form>
{ image && <img src={image}/>}
</div>
)
}
Backend
const express = require('express')
const fs = require('fs')
const multer = require('multer')
const upload = multer({ dest: 'images/' })
const app = express()
app.use('/images', express.static('images'))
app.get('/images/:imageName', (req, res) => {
// do a bunch of if statements to make sure the user is
// authorized to view this image, then
const imageName = req.params.imageName
const readStream = fs.createReadStream(`images/${imageName}`)
readStream.pipe(res)
})
app.post('/api/images', upload.single('image'), (req, res) => {
const imagePath = req.file.path
const description = req.body.description
// Save this data to a database probably
console.log(description, imagePath)
res.send({description, imagePath})
})
app.listen(8080, () => console.log("listening on port 8080"))
routes/Test.js
const express = require("express");
const router = express.Router();
module.exports = router;
const auth_util = require("../utilities/auth_util");
const pgclient = require("../app");
const multer = require('multer')
const upload = multer({ dest: 'images/' })
router.get('/images/:imageName', (req, res) => {
// do a bunch of if statements to make sure the user is
// authorized to view this image, then
const imageName = req.params.imageName
const readStream = fs.createReadStream(`images/${imageName}`)
readStream.pipe(res)
})
router.post('/api/images', upload.single('image'), (req, res) => {
console.log(req.file)
console.log(req.files)
const imagePath = req.file.path
const description = req.body.description
// Save this data to a database probably
console.log(description, imagePath)
res.send({ description, imagePath })
})
// added the lines below
const path = require("path");
router.use(express.static(path.join(__dirname, 'build')));
router.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.js
const express = require("express");
const cors = require("cors");
//const fileUpload = require("express-fileupload");
const session = require("express-session");
const { Pool } = require("pg");
const app = express();
app.use(express.json());
//app.use(fileUpload());
//------------------------------CORS settings------------------------------
var whitelist = [
"http://localhost:3000",
"http://localhost:3001",
];
var corsOptions = {
credentials: true,
exposedHeaders: ["set-cookie"],
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true);
} else {
// callback(null, true)
callback(new Error("Not allowed by
<details>
<summary>英文:</summary>
*EDIT*
I removed `app.use(fileUpload());`. So it finally worked.
But unfortunately in the folder `images` of the `backend` I only get these files `c43jnfeh734hdfudf`.
For this reason, nothing is displayed in the frontend.
const imagePath = req.file.path
const description = req.file.originalname
console.log(imagePath)
console.log(description)
images\c43jnfeh734hdfudf
empty
----------
I have a problem. I would like to save images with a fixed URL on my server.
I found the following code snippet, but unfortunately it doesn't work.
I get the following error in the backend: `'TypeError: Cannot read property 'path' of undefined'`.
The following values are `'undefined'`. `const imagePath = req.file.path` `const description = req.body.description`
How can I save an image as a URL on the server?
Here is the tutorial, where I found the code snippet https://github.com/meech-ward/sammeechward.com_mdx/blob/master/content/articles/uploading-images-express-and-react/index.mdx
**React**
```js
import { useState } from 'react'
import axios from 'axios'
export default function App() {
const [file, setFile] = useState()
const [description, setDescription] = useState("")
const [image, setImage] = useState()
const submit = async event => {
event.preventDefault()
const formData = new FormData()
formData.append("image", file)
formData.append("description", description)
const result = await axios.post('/api/images', formData, { headers: {'Content-Type': 'multipart/form-data'}})
setImage(result.data.imagePath)
}
return (
<div className="App">
<form onSubmit={submit}>
<input
filename={file}
onChange={e => setFile(e.target.files[0])}
type="file"
accept="image/*"
></input>
<input
onChange={e => setDescription(e.target.value)}
type="text"
></input>
<button type="submit">Submit</button>
</form>
{ image && <img src={image}/>}
</div>
)
}
Backend
const express = require('express')
const fs = require('fs')
const multer = require('multer')
const upload = multer({ dest: 'images/' })
const app = express()
// app.use('/images', express.static('images'))
app.get('/images/:imageName', (req, res) => {
// do a bunch of if statements to make sure the user is
// authorized to view this image, then
const imageName = req.params.imageName
const readStream = fs.createReadStream(`images/${imageName}`)
readStream.pipe(res)
})
app.post('/api/images', upload.single('image'), (req, res) => {
const imagePath = req.file.path
const description = req.body.description
// Save this data to a database probably
console.log(description, imagePath)
res.send({description, imagePath})
})
app.listen(8080, () => console.log("listening on port 8080"))
routes/Test.js
const express = require("express");
const router = express.Router();
module.exports = router;
const auth_util = require("../utilities/auth_util");
const pgclient = require("../app");
const multer = require('multer')
const upload = multer({ dest: 'images/' })
// app.use('/images', express.static('images'))
router.get('/images/:imageName', (req, res) => {
// do a bunch of if statements to make sure the user is
// authorized to view this image, then
const imageName = req.params.imageName
const readStream = fs.createReadStream(`images/${imageName}`)
readStream.pipe(res)
})
router.post('/api/images', upload.single('image'), (req, res) => {
console.log(req.file)
console.log(req.files)
const imagePath = req.file.path
const description = req.body.description
// Save this data to a database probably
console.log(description, imagePath)
res.send({ description, imagePath })
})
// added the lines below
const path = require("path");
router.use(express.static(path.join(__dirname, 'build')));
router.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.js
const express = require("express");
const cors = require("cors");
//const fileUpload = require("express-fileupload");
const session = require("express-session");
const { Pool } = require("pg");
const app = express();
app.use(express.json());
//app.use(fileUpload());
//------------------------------CORS settings------------------------------
var whitelist = [
"http://localhost:3000",
"http://localhost:3001",
];
var corsOptions = {
credentials: true,
exposedHeaders: ["set-cookie"],
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true);
} else {
// callback(null, true)
callback(new Error("Not allowed by CORS!!"));
}
},
};
app.options("*", cors(corsOptions));
const pgclient = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_DATABASE,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
});
module.exports = pgclient;
app.set("trust proxy", 1);
const testRoute = require("./routes/test");
app.use("/test", cors(corsOptions), testRoute);
app.get("/", cors(corsOptions), (req, res, next) => {
res.send("Welcome");
});
module.exports = app;
答案1
得分: 1
根据这个回答,multer在文件上传中使用了一种类型的cookie,过时的cookie版本会导致文件上传失败。尝试清除您浏览器的cookie。
为了避免跨域策略,前端和后端必须都托管在同一端口上,所以我添加了一个GET路由来从expressjs服务器上静态地提供react页面:
const express = require('express')
const fs = require('fs')
const multer = require('multer')
const upload = multer({ dest: 'images/' })
const app = express()
// app.use('/images', express.static('images'))
app.get('/images/:imageName', (req, res) => {
// 执行一系列的if语句来确保用户被授权查看这个图片,然后
const imageName = req.params.imageName
const readStream = fs.createReadStream(`images/${imageName}`)
readStream.pipe(res)
})
app.post('/api/images', upload.single('image'), (req, res) => {
console.log(req.file)
console.log(req.files)
const imagePath = req.file.path
const description = req.body.description
// 可能将这些数据保存到数据库中
console.log(description, imagePath)
res.send({ description, imagePath })
})
// 添加了下面的行
const path = require("path");
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(8080, () => console.log("监听端口8080"))
英文:
According to this answer, multer uses a kind of cookie in its file uploads and out of date versions of the cookie cause the file upload to fail. Try clearing your browser's cookies.
https://stackoverflow.com/questions/35851660/multer-req-file-always-undefined
Edit: here is the script working on my end with some images:
I did have to make one minor edit to get the example to work on chrome. To avoid the CORS policy, the front and back end must both be hosted at the same port. So, I added get route to statically serve the react page from the expressjs server:
const express = require('express')
const fs = require('fs')
const multer = require('multer')
const upload = multer({ dest: 'images/' })
const app = express()
// app.use('/images', express.static('images'))
app.get('/images/:imageName', (req, res) => {
// do a bunch of if statements to make sure the user is
// authorized to view this image, then
const imageName = req.params.imageName
const readStream = fs.createReadStream(`images/${imageName}`)
readStream.pipe(res)
})
app.post('/api/images', upload.single('image'), (req, res) => {
console.log(req.file)
console.log(req.files)
const imagePath = req.file.path
const description = req.body.description
// Save this data to a database probably
console.log(description, imagePath)
res.send({ description, imagePath })
})
// added the lines below
const path = require("path");
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(8080, () => console.log("listening on port 8080"))
答案2
得分: 1
首先,你需要移除 express-fileupload
。在使用 multer
时不需要同时使用它。
为了在指定文件夹中得到正确的带扩展名的文件,你需要更改你的代码的这一部分:
移除这行:
const upload = multer({ dest: 'images/' })
改成:
// routes/Test.js
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'images')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
const upload = multer({ storage: storage })
为了以常规和标准的方式防止相同文件名的覆盖,你需要将 filename
更改为以下内容:
filename: function (req, file, cb) {
cb(null, `${Date.now()}-${file.originalname}`)
}
英文:
First of all, you need to remove express-fileupload
. There is no need to use it alongside multer
.
To have the correct file with an extension in specified folder, you need to change this part of your code:
remove this line:
const upload = multer({ dest: 'images/' })
change it to:
// routes/Test.js
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'images')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
const upload = multer({ storage: storage })
For conventional and standard way to prevent overwriting the same file names, you need to change filename
to this:
filename: function (req, file, cb) {
cb(null, `${Date.now()}-${file.originalname}`)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论