使用 MongoDB、express、node 和 react 上传图片

Posted

技术标签:

【中文标题】使用 MongoDB、express、node 和 react 上传图片【英文标题】:Uploading images with MongoDB, express, node, and react 【发布时间】:2020-11-06 14:54:33 【问题描述】:

我一直在关注 YouTube 上的这个很棒的教程,试图建立一个网站。但是,一旦我部署它,图像就不会显示,因为目前它们都保存在一个名为 uploads 的本地文件夹中。这就是它现在的样子:

服务器端

var storage = multer.diskStorage(
    destination: (req, file, cb) => 
        cb(null, 'uploads/')
    ,
    filename: (req, file, cb) => 
        cb(null, `$Date.now()_$file.originalname`)
    ,
    fileFilter: (req, file, cb) => 
        const ext = path.extname(file.originalname)
        if (ext !== '.jpg' || ext !== '.png') 
            return cb(res.status(400).end('only jpg, png are allowed'), false);
        
        cb(null, true)
    
)

var upload = multer( storage: storage ).single("file")

router.post("/uploadImage", auth, (req, res) => 

    upload(req, res, err => 
        if(err) return res.json(success: false, err)
        return res.json( success: true, image: res.req.file.path, fileName: res.req.file.filename)
    )
   
);

CLIENT SIDE:图片字段存储一个字符串(即“uploads\xxxxxxxx.jpg”)

function ProductImage(props) 

    const [Image, setImage] = useState();

    useEffect(() => 
        setImage(`http://localhost:5000/$props.detail.image`)
        

    , [props.detail])
    
    return(
        <div>
            <img style=maxWidth: '30vw' 
            src=Image />
        </div>
    )

所以我想我现在的问题是我该如何实际将图像上传到 MongoDB,以及如何检索它们?

【问题讨论】:

【参考方案1】:

首先,将原始图像数据存储在任何数据库中都不是明智的选择。

你必须做三件事来处理文件:

1.在您的数据集合中创建一个字符串字段,用于存储文件名和您希望在主机中存储图像的路径。

    上传控制器:

在上传控制器中,您可以处理上传的逻辑,例如存储数据、验证文件,以及当文件到达服务器时,您可以将路径存储在数据库中。

3. 使用express 提供您的静态文件:

router.use(
    "/avatar",
    express.static(path.join(__dirname, "../upload/avatar"))
);

【讨论】:

感谢您的回复!我相信我已经完成了您在此处列出的所有内容,我上传的所有图片所在的文件夹都是静态的。问题是部署到heroku后,图像不会显示。我很确定这是因为当我检索图像时,我使用了http://localhost:5000/$props.detail.image,这在 heroku 上运行时没有意义。关于这行代码应该是什么的任何建议?【参考方案2】:

如果您将上传的图像存储在 Heroku 服务器中,那是完全浪费的。因为 Heroku Dyno 每天都会重新启动,这将删除所有额外添加的数据,而不是在部署期间存储的数据。

首先要上传到 MongoDB,你需要将它存储到服务器,multer 完成这项工作,然后它会自动从 heroku 中删除。 下面的代码会加密您的数据并根据 id 将其上传到特定文档。

//Hashing and uploading to Mongodb 
fs.readFile('your file location', async function (err, data) 
    if (err) 
        console.log(err)
     else 
        let iv = crypto.randomBytes(16);
        let pass = //I think 32 char password is required
        let cipher = crypto.createCipheriv('aes-256-ctr', pass, iv)
        let crypted = Buffer.concat([iv, cipher.update(data), cipher.final()]);


        console.log("crypted", crypted);
        let dataa = await User.findOne(
            _id: "Id of a MongoDB document"
        )
        //let buffer=new Buffer(data)
        dataa.files.push(crypted)
        await dataa.save()
        console.log("done")
    

);

检索和解密数据

let data = await User.findOne(
    _id: "id of a MongoDB document"
)
console.log("dattttt", data.files[index of your image in mongoarray].buffer)


iv = data.files[index of your image in mongoarray].buffer.slice(0, 16);
chunk = data.files[index of your image in mongoarray].buffer.slice(16);
var decipher = crypto.createDecipheriv('aes-256-ctr', "same 32 char password here", iv)
var dec = Buffer.concat([decipher.update(chunk), decipher.final()]);

console.log("dec", dec);
let buffer = new Buffer.from(dec)
console.log("buffer", buffer)
fs.writeFile(`downloadable file location/filename.extension`, buffer, "binary", function (err, written) 
    if (err) console.log(err);
    else 
        console.log("Successfully written");
        res.sendFile((__dirname + `downloaded file location/filename.extension`))
    
);

【讨论】:

以上是关于使用 MongoDB、express、node 和 react 上传图片的主要内容,如果未能解决你的问题,请参考以下文章

使用 MongoDB、express、node 和 react 上传图片

使用node+express+mongodb实现用户注册登录和验证功能

将 Node、Express 和 MongoDB 服务器部署到 heroku

无法将值传递到 MongoDB,使用 Node 和 Express,Mongoose

使用 Express 和 Node JS 在 MongoDB 中上传文本文件

如何使用 mongodb、node.js、express 和 EJS 创建动态站点地图?