0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Node.js Express】EXCELファイルをバックアップし、DBに格納

Last updated at Posted at 2020-02-17

エクセルファイルをアップロードしたら、バックアップを作成し、中身のデータをデータベースに登録するAPIを作りました。また似たような作業することになりそうなので、メモ。
Node.jsとExpress、データベースはMysqlを使用

#使うもの
1)multer
アップロードされたエクセルファイルを特定のファイルにコピーする。
※ただし、multipart/form-dataのみ
https://www.npmjs.com/package/multer

インストール:
npm install --save multer

2)sheetjs
エクセルファイルの書き換え等ができる。
今回はエクセルファイルをJSONに変換するのに使用した。
https://www.npmjs.com/package/xlsx

インストール:
npm install --save xlsx

#実装

const express = require('express')
const app = express()
const models = require('../model/models')
const xlsx = require('xlsx')
const multer = require('multer')
const storage = multer.diskStorage({
    //保存先を指定
  destination: function (req, file, cb) {
    cb(null, './uploads/excels')
  },
    //ファイル名の先端に日付をつけて保存
  filename:  function (req, file, cb) {
    cb(null, new Date().toISOString() + file.originalname)
  }
})

const fileFilter = (req, file, cb) => {
  //ファイルの拡張子を確認 とりあえず、excelとspredsheetを。
  if (file.mimetype === 'application/vnd.ms-excel' || file.minetype === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
    cb(null, true)
  } else {
    cb(null, false)
  }
}


const upload = multer({
  storage: storage,
  limits: {
    //アップロードできるファイル数
    files: 1,
    //ファイルサイズ(2MB@)
    fieldSize: 2 * 1024 * 1024
  },
  fileFilter: fileFilter
})

app.post('/upload' , upload.single('postしてくる時のキー'), async(req, res) => {
  try {
    const sheet = xlsx.readFile('./uploads/excels/' + req.file.filename, { cellDates: true })
    const workingSheet = sheet.Sheets['シート名']
    const data = xlsx.utils.sheet_to_json(workingSheet)
    //カラム名
    const fieldNames = ['date', 'name', 'tel']
    var dataArray = []
    for (var i in data) {
      //String型を明記しないとエラーになったので。 
      //エクセルのカラム名?(カラム最上セルのテキスト)日本語なのがアレなので良い方法あれば教えて欲しいです。
      //電話番号は -(ハイフン) を抜き取る。
      var insertData = `(${JSON.stringify(data[i].日付) || null}, ${JSON.stringify(data[i].名前) || null}, , ${data[i].電話番号.replace(/-/g, '') || null})`
      dataArray.push(insertData)
    }
    const tableName = 'テーブル名'
    //毎回データを総入れ替えする仕様のため、全データ消す
    const areDeleted = await models.deleteAll(tableName)
    if (!areDeleted) return res.status(500).json({ message: 'エラーが発生!' })
    //データを挿入
    const areInserted = await models.insertData(tableName, fieldNames, dataArray)
    if (!areInserted) return res.status(500).json({ message: 'エラー発生!' })
    return res.status(200).json({ message: '成功!' })
  } catch (err) {
    console.log(err)
    return res.status(500).json({ message: 'エラーが発生!' })
  }
})

モデル抜粋

model.js
const mysql = require('mysql2')
const models = {}

// Setup database
const connection = mysql.createConnection({
  host: ホスト,
  user: ユーザー,
  password: パスワード,
  database: データベース名,
  port: ポート番号,
  multipleStatements: true //複数のコールを有効化
})

connection.connect((err) => {
  if (!err)
    console.log('接続成功')
  else
    console.log('接続失敗 : ' + JSON.stringify(err, undefined, 2))
})

models.deleteAll = (tableName) => {
  return new Promise((resolve, reject) => {
    connection.query('DELETE FROM ?', [tableName], (err, results) => {
      if (err) return reject(err)
      else return resolve(results)
    })
  })
}

models.insertData = (tableName, fieldName, insertData) => {
  return new Promise((resolve, reject) => {
    connection.query(`INSERT INTO ? (?) VALUES ?`, [tableName, fieldName, insertData],(err, results) => {
      if (err) return reject(err)
      else return resolve(results)
    })
  })
}

module.exports.models = models



0
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?