如何将图像保存到服务器并生成一个URL?

huangapple go评论86阅读模式
英文:

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&#39;t work. 
I get the following error in the backend: `&#39;TypeError: Cannot read property &#39;path&#39; of undefined&#39;`.

The following values are `&#39;undefined&#39;`. `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 &#39;react&#39;
import axios from &#39;axios&#39;

export default function App() {
  const [file, setFile] = useState()
  const [description, setDescription] = useState(&quot;&quot;)
  const [image, setImage] = useState()

  const submit = async event =&gt; {
    event.preventDefault()

    const formData = new FormData()
    formData.append(&quot;image&quot;, file)
    formData.append(&quot;description&quot;, description)

    const result = await axios.post(&#39;/api/images&#39;, formData, { headers: {&#39;Content-Type&#39;: &#39;multipart/form-data&#39;}})
    setImage(result.data.imagePath)
  }

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;form onSubmit={submit}&gt;
        &lt;input
          filename={file} 
          onChange={e =&gt; setFile(e.target.files[0])} 
          type=&quot;file&quot; 
          accept=&quot;image/*&quot;
        &gt;&lt;/input&gt;
        &lt;input
          onChange={e =&gt; setDescription(e.target.value)} 
          type=&quot;text&quot;
        &gt;&lt;/input&gt;
        &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
      &lt;/form&gt;
      { image &amp;&amp; &lt;img src={image}/&gt;}
    &lt;/div&gt;
  )
}

Backend

const express = require(&#39;express&#39;)
const fs = require(&#39;fs&#39;)
const multer = require(&#39;multer&#39;)

const upload = multer({ dest: &#39;images/&#39; })

const app = express()

// app.use(&#39;/images&#39;, express.static(&#39;images&#39;))
app.get(&#39;/images/:imageName&#39;, (req, res) =&gt; {
  // 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(&#39;/api/images&#39;, upload.single(&#39;image&#39;), (req, res) =&gt; {
  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, () =&gt; console.log(&quot;listening on port 8080&quot;))

routes/Test.js

const express = require(&quot;express&quot;);
const router = express.Router();
module.exports = router;
const auth_util = require(&quot;../utilities/auth_util&quot;);
const pgclient = require(&quot;../app&quot;);
const multer = require(&#39;multer&#39;)
const upload = multer({ dest: &#39;images/&#39; })

// app.use(&#39;/images&#39;, express.static(&#39;images&#39;))
router.get(&#39;/images/:imageName&#39;, (req, res) =&gt; {
  // 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(&#39;/api/images&#39;, upload.single(&#39;image&#39;), (req, res) =&gt; {
  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(&quot;path&quot;);

router.use(express.static(path.join(__dirname, &#39;build&#39;)));

router.get(&#39;/&#39;, function (req, res) {
  res.sendFile(path.join(__dirname, &#39;build&#39;, &#39;index.html&#39;));
});

app.js

const express = require(&quot;express&quot;);
const cors = require(&quot;cors&quot;);
//const fileUpload = require(&quot;express-fileupload&quot;);
const session = require(&quot;express-session&quot;);
const { Pool } = require(&quot;pg&quot;);



const app = express();

app.use(express.json());
//app.use(fileUpload());
//------------------------------CORS settings------------------------------
var whitelist = [
	&quot;http://localhost:3000&quot;,
	&quot;http://localhost:3001&quot;,
];
var corsOptions = {
	credentials: true,
	exposedHeaders: [&quot;set-cookie&quot;],
	origin: function (origin, callback) {
		if (whitelist.indexOf(origin) !== -1 || !origin) {
			callback(null, true);
		} else {
			// callback(null, true)
			callback(new Error(&quot;Not allowed by CORS!!&quot;));
		}
	},
};
app.options(&quot;*&quot;, 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(&quot;trust proxy&quot;, 1);


const testRoute = require(&quot;./routes/test&quot;);
app.use(&quot;/test&quot;, cors(corsOptions), testRoute);

app.get(&quot;/&quot;, cors(corsOptions), (req, res, next) =&gt; {
	res.send(&quot;Welcome&quot;);
});

module.exports = app;

答案1

得分: 1

根据这个回答,multer在文件上传中使用了一种类型的cookie,过时的cookie版本会导致文件上传失败。尝试清除您浏览器的cookie。

编辑:以下是在我的端口上使用一些图片工作的脚本:
如何将图像保存到服务器并生成一个URL?

为了避免跨域策略,前端和后端必须都托管在同一端口上,所以我添加了一个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:
如何将图像保存到服务器并生成一个URL?

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(&#39;express&#39;)
const fs = require(&#39;fs&#39;)
const multer = require(&#39;multer&#39;)
const upload = multer({ dest: &#39;images/&#39; })
const app = express()
// app.use(&#39;/images&#39;, express.static(&#39;images&#39;))
app.get(&#39;/images/:imageName&#39;, (req, res) =&gt; {
// 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(&#39;/api/images&#39;, upload.single(&#39;image&#39;), (req, res) =&gt; {
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(&quot;path&quot;);
app.use(express.static(path.join(__dirname, &#39;build&#39;)));
app.get(&#39;/&#39;, function (req, res) {
res.sendFile(path.join(__dirname, &#39;build&#39;, &#39;index.html&#39;));
});
app.listen(8080, () =&gt; console.log(&quot;listening on port 8080&quot;))

答案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: &#39;images/&#39; })

change it to:

// routes/Test.js
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, &#39;images&#39;)
},
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}`)
}

huangapple
  • 本文由 发表于 2023年1月9日 15:43:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75054343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定