ENOENT:没有这样的文件或目录。

42
我在提交数据和文件时遇到了错误。 我按照'academind'的Restful API服务教程进行操作,也一直在寻找解决此类错误的答案,但都没有起作用。 我使用"multer"来上传文件。 虽然'uploads'文件夹存在,但显示如下错误: ENOENT: 没有这样的文件或目录,打开'D:\project\uploads\2018-01-24T07:41:21.832Zcheck.jpg'"。 代码文件为'app.js'。
const express = require("express");
const app = express();
const morgan = require("morgan");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");

const productRoutes = require("./api/routes/products");

mongoose.connect('',
(err)=>{
    if(err){console.log(err)}
    else{console.log('DB Connected')}
})
mongoose.Promise = global.Promise;

app.use(morgan("dev"));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Authorization"
  );
  if (req.method === "OPTIONS") {
    res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
    return res.status(200).json({});
  }
  next();
});

// Routes which should handle requests
app.use("/products", productRoutes);

app.use((req, res, next) => {
  const error = new Error("Not found");
  error.status = 404;
  next(error);
});

app.use((error, req, res, next) => {
  res.status(error.status || 500);
  res.json({
    error: {
      message: error.message
    }
  });
});

module.exports = app;

product.js

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const multer = require('multer');

const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    cb(null, './uploads/');
  },
  filename: function(req, file, cb) {
    cb(null, new Date().toISOString() + file.originalname);
  }
});

const fileFilter = (req, file, cb) => {
  // reject a file
  if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 1024 * 1024 * 5
  },
  fileFilter: fileFilter
});

router.post("/", checkAuth, upload.single('productImage'), (req, res, next) => {
  const product = new Product({
    _id: new mongoose.Types.ObjectId(),
    name: req.body.name,
    price: req.body.price,
    productImage: req.file.path 
  });
  product
    .save()
    .then(result => {
      console.log(result);
      res.status(201).json({
        message: "Created product successfully",
        createdProduct: {
            name: result.name,
            price: result.price,
            _id: result._id,
            request: {
                type: 'GET',
                url: "http://localhost:3000/products/" + result._id
            }
        }
      });
    })
    .catch(err => {
      console.log(err);
      res.status(500).json({
        error: err
      });
    });
});

module.exports = router;

根据此页面,文件名中不允许使用冒号(:)。请尝试删除它(在 product.js 的第11行)。 - RickN
29个回答

97

在 product.js 中:

new Date().toISOString() 之后添加 replace() 来将“:” 替换为可以接受的字符。

Windows 操作系统不接受带有“:”的文件名。

Youtuber 使用的是 MAC 操作系统。

例如:

new Date().toISOString().replace(/:/g, '-')


6
谢谢你。我也遇到了同样的问题,这解决了我的问题。 - nikola_wd
这个回答值得更多的赞。 - Ahmad Habib

23

请尝试以下操作:

  1. 将其作为常量进行引用 (const path = require('path');)
  2. 更改此行代码

    cb(null, './uploads/');

用以下内容替换:

cb(null, path.join(__dirname, '/uploads/'));

我看到你正在尝试获取的路径不是服务器上提供的路径,而是服务器机器上的路径。

更新

也尝试更改这个。

app.use('/uploads', express.static('uploads'));

变成这样:

app.use(express.static(__dirname));

为了将__dirname暴露给静态文件。


我已经添加了“cb(null, 'D:/project/uploads');”,但仍然相同。 - codedamn
不要使用“D:/project/uploads”,而要使用__dirname全局对象。 - Igor Dimchevski
相同的错误,console.log(__dirname) 的结果为 D:\project。 - codedamn
错误一定是出现在express.static上,它无法托管您的静态文件夹。 - Igor Dimchevski
3
非常感谢您。这让我省去了很多时间和压力。添加next(null, path.join(__dirname, '.././public/uploads/images/'));生效了。 - Kipruto

7

所以答案在 YouTube 上的教程评论部分。

cb(null, new Date().toISOString() + file.originalname);

做:

cb(null, Date.now() + file.originalname);

简单易懂。

6

以下是我的做法。我将'./uploads/'改为'__dirname',这样它就可以在电脑上的任何地方找到正确的目录/文件名。

const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    cb(null, __dirname);
  },
  filename: function(req, file, cb) {
    cb(null, new Date().toISOString() + file.originalname);
  }
});

因为当您设置特定的文件夹名称/目录时,您会将图像目录限制为仅在该文件夹中或应该在该文件夹中。

谢谢。它正在工作。 - Archana SIngh
谢谢。这对我有用,但我不知道为什么一开始会出现这样的错误。 - Gregzone

4

我正在学习相同的课程,我也遇到了相同的问题(我也使用Windows电脑)。以下方法对我有用:

const hash = require('random-hash'); // you have to install this package:

const fileStorage = multer.diskStorage({
    destination: (req, file, callback) => { //this is storing the file in the images folder
        callback(null, path.join(__dirname, '/Images'));
    },

    filename: (req, file, callback) => { //this is just setting a unique filename
        let temp = file.originalname.split('.');
        const filename = temp[0] + '-' + hash.generateHash({length: 5}) + '.' + temp[1]
        callback(null, filename);
    }
});

这还为文件名创建了一个独特的哈希值


你也可以使用Node内置的加密库来生成哈希值。这样,您就不必添加其他依赖项。crypto.randomBytes(16).toString("hex") -> 这一部分将生成哈希值。 - Tom Bombadil

3
我在评论区看到了这个内容,链接在这里:https://www.youtube.com/watch?v=srPXMt1Q0nY&list=PL55RiY5tL51q4D-B63KBnygU6opNPFk_q&index=10 OK,大家好,如果你在文件创建阶段遇到问题,那可能意味着你正在使用Windows。现在,你不需要感到沮丧并扔掉你的电脑(我其实喜欢为我的Windows寻找解决方法 :)。 至少有一个解决方案,这是我找到的。我的问题是文件没有被创建,因为Windows不接受带有冒号(':')的文件名。我的解决方案相当简单。在获取当前日期后,我使用replace()和一个正则表达式将其更改为破折号。就这样,它有效了!
以防万一,这是一种做法: filename: function(req, file, cb){ const now = new Date().toISOString(); const date = now.replace(/:/g, '-'); cb(null, date + file.originalname); } 希望对在Windows上工作的人有所帮助。

2
这个错误是因为./uploads/不存在导致的。 提示: 如果您像下面这样使用 multer const upload = multer({ dest: 'uploads' }) 这将在服务器启动时创建 uploads 目录。
但是,如果我们使用 destination 对象,则不会创建目录。 证明/参考: https://www.npmjs.com/package/multer#diskstorage https://www.npmjs.com/package/multer#diskstorage 解决方案
const fs = require('fs'); // Added to create directories
const multer = require('multer');

const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    // :::::::::::::::Create diretories:::::::::::::::::::
    fs.mkdir('./uploads/',(err)=>{
       cb(null, './uploads/');
    });
  },
  filename: function(req, file, cb) {
    cb(null, new Date().toISOString() + file.originalname);
  }
});

const fileFilter = (req, file, cb) => {
  // reject a file
  if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 1024 * 1024 * 5
  },
  fileFilter: fileFilter
});

2

我曾遇到类似的错误,以下是我的解决方法。使用replace方法之后,我将'./uploads/images/'改为了'uploads/images'。在这种情况下,multer会自动创建文件夹,因此你会得到如下结果:

const storage = multer.diskStorage({
    destination: function(req, file, cb) {
    cb(null, 'uploads/');
    },
    filename: function(req, file, cb) {
     cb(null, new Date().toISOString().replace(/:/g, '-')+ file.originalname);
      }
  });

对于Windows用户。


2

在保存文件时,我遇到了相同的错误。 回调函数中提供的路径并不存在,所以我才会得到那个错误。

const fs = require('fs');
const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    fs.mkdir('./uploads/',(err)=>{
       cb(null, './uploads/');
    });
  },
  filename: function(req, file, cb) {
    cb(null, new Date().toISOString() + file.originalname);
  }
});

我使用文件系统创建了相同的文件夹,如果文件夹存在,则会得到一个err值,但是由于我们已经有了这个文件夹,所以不用担心。这对我很有效,希望能帮到你。


1
是啊...我花了一个小时才弄清楚文件夹应该已经存在,然后它才保存文件。 - Ajay Rawat

1

一切都很好。问题出在这行代码上: cb(null, new Date().toISOString() + file.originalname); 只需简单地写成:cb(null,file.originalname); 它会正常工作。尝试以不同的方式添加日期字符串与文件名。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接