在上载到Multer gridfs存储中的mongodb之前,先转换文件类型(例如:将csv转换为json)

时间:2018-06-19 12:09:32

标签: node.js mongodb mongoose multer gridfs

我正在使用multer的gridfs存储引擎将文件从浏览器上传到mongodb数据库。

我需要允许用户上传csv和json文件类型(以后再上传)。在将文件上传到数据库之前,如何检查文件类型是否为csv并将其转换为json。

我使用了多个npm软件包,例如csvtojson,papaparse。使用papaparse我可以将文件类型转换为json,但是我似乎无法在存储/上传中访问它。

这是我到目前为止所做的。

const storage = new GridFsStorage({
    url: "",
    file: (req, file) => {
        return new Promise((resolve, reject) => {
            const filename = `${new Date()
        .toJSON()
        .slice(0, 10)
        .split("-")
        .reverse()
        .join(".")} - ${file.originalname}`;
            const fileInfo = {
                filename,
                bucketName: "uploads"
            };
            resolve(fileInfo);
        });
    }
});
const upload = multer({
    storage,
    fileFilter: function(req, file, cb) {
        var filetypes = /json|csv/;
        var mimetype = filetypes.test(file.mimetype);
        var extname = filetypes.test(path.extname(file.originalname).toLowerCase());

        if (mimetype && extname) {
            return cb(null, true);
        }
        cb({
            fileTypeError: "File upload only supports the following filetypes - " + filetypes
        });
    }
});

const fileUpload = upload.single("file");

// create mongo connection
const conn = mongoose.createConnection(mongoURI);

// Init gfs
let gfs;

conn.once("open", () => {
    console.log("connection open");
    gfs = Grid(conn.db, mongoose.mongo);
    gfs.collection("uploads");
});

app.use(bodyParser.json({
    limit: "50mb"
}));
app.use(
    bodyParser.urlencoded({
        extended: true,
        limit: "50mb",
        parameterLimit: 1000000
    })
);


// @route   POST api/logs/upload
// @desc    Upload file
// @access  Public

app.post("/api/logs/upload", (req, res) => {
    fileUpload(req, res, function(err) {
        if (err) {
            return res.status(501).json(err);
        }
        //send back file data
        //req.body is empty here too
        res.json({
            file: req.file
        });
    });
});

  onSubmit(e) {
    const { addLogFile } = this.props;

    e.preventDefault();
    let formData = new FormData();

    const file = this.fileInput.files[0];
    console.log(file);

    if (file.type === "application/vnd.ms-excel") {
      Papa.parse(file, {
        header: true,
        complete: function(results) {
          file.csv = results.data;
          formData.append("file", file);

          addLogFile(formData);
        }
      });
    } else if (file.type === "application/json") {
      formData.append("file", file);
      addLogFile(formData);
    } else {
      alert("not supported");
    }

    // clear file input
    document.getElementById("file").value = "";
  }

  

  render() {
    return (
      <div className="logs">
        <form encType="multipart/form-data" onSubmit={this.onSubmit}>
          <input
            name="file"
            type="file"
            id="file"
            ref={input => {
              this.fileInput = input;
            }}
            onChange={this.onChange}
            required
            accept="application/json, .csv"
          />
          <button>
            Upload
          </button>
        </form>
        

      </div>
    );
  }

在哪里可以访问文件详细信息和csv文件?还是有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:0)

您必须创建自己的存储引擎(https://github.com/expressjs/multer/blob/master/StorageEngine.md

_handleFile方法中,您可以访问文件路径,该路径可用于转换文件。然后,如果您想使用gridfs,我建议绕过gridfs-storage-engine模块(顺便说一句,自2016年以来未曾使用过)。只要看一下https://github.com/ISMAELMARTINEZ/gridfs-storage-engine/blob/master/lib/GridfsStorage.js#L47上的代码,就可以做到:

MyCustomStorage.prototype._handleFile = function _handleFile (req, file, cb) {
  this.getDestination(req, file, function (err, path) {
    if (err) return cb(err)
    const writestream = gfs.createWriteStream({
      filename: file.originalname,
      metadata: req.body,
      content_type: file.mimetype
    });

    file.stream.pipe(csv()).pipe(writestream);
    writestream.on('close', function (file) {
      console.log('gridfs-storage-engine: saved', file);
      cb(null, { gridfsEntry: file });
    });
  });
}