6
1

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 5 years have passed since last update.

Node.jsとexpressで作成したWebAPIでファイルの読み書きを行う

Posted at

概要

Node.jsとexpressを使って作成したWebAPIで、ファイルの書き出しとファイルの読込を行いたい。

環境

Windows 10
Node.js v8.9.1
npm 5.5.1
express 4.16.0
express-generator
Google Chrome 71.0.3578.98
Visual Studio Code

前提

前回の記事で、Node.jsとexpressで簡単なWebAPIを作成・動作確認できていること。
Node.jsとexpressを使って簡単なWebAPIを作成する

ファイルへの書き出し(簡単編)

Nodeのfsモジュールに入っているfs.writeFile()でファイルへの書き出しを行う。

nodejs.org - fs.writeFile

コード

index.js
const express = require('express');
const app = express();
const fs = require('fs');

// ルート設定
app.get('/', (req, res) => res.send('Hello World'));

// api-create-request-fileの設定
app.get('/api/v1/create-request-file', (req, res) =>{
    fs.writeFile("C:/test/request.txt" , "書き込みデータ" , (err) => {
        if(err){
            return res.status(500).send("エラーが発生しました");
        }
        else{
            return res.status(200).send("ファイルが正常に書き出しされました");
        }
    });
});

// イベント待機
app.listen(3000, () => console.log('Listening on port 3000'));

実行結果

正常に書き出せた場合

正常にファイルに書き込みができた場合、ステータスコード200(正常)がHTTPレスポンスとして返される。

WS000083.JPG

正常に書き出せなかった場合

指定されたパスが無いなど、正常に書き出せなかった場合はステータスコード500(サーバエラー)がHTTPレスポンスとして返される。

WS000082.JPG

ファイルへの書き出し(ちゃんとチェックする編)

簡単編ではフォルダの存在有無やアクセス権をチェックせず、writeFileでいきなりファイルの書き込みを行っているが、実際にはフォルダの存在有無やアクセス権をチェックした方がよい。

コード

index.js
const express = require('express');
const app = express();
const fs = require('fs');
const path = require('path');

// ルート設定
app.get('/', (req, res) => res.send('Hello World'));

// api-create-request-fileの設定
app.get('/api/v1/create-request-file', (req, res) =>{
    var filePath = "C:/test/request.txt"
    var dirName = path.dirname(filePath);
    fs.access(dirName, fs.constants.R_OK | fs.constants.W_OK, (err) => {
        if (err) {
            if (err.code === "ENOENT") {
                fs.mkdirSync(dirName);
                console.log("フォルダ " + dirName + " を作成しました");
            } else {
                console.log("フォルダ " + dirName + " の書き込み権限がありません");
                return res.status(500).send("エラーが発生しました");
            } 
        }

        fs.writeFile(filePath , "書き込みデータ" , (err) => {
            if(err){
                return res.status(500).send("エラーが発生しました");
            }
            else{
                return res.status(200).send("ファイルが正常に書き出しされました");
            }
        });
    });
});

// イベント待機
app.listen(3000, () => console.log('Listening on port 3000'));

コードの解説

fs.stat() or fs.access()

Nodeでディレクトリの有無を確かめるにはfs.stat()fs.access()を使用するが、書き込みを行うのであれば書き込み権限もまとめてチェックできた方がいいので今回はfs.access()を使用している。

nodejs.org - fs.access

fs.access()は第一引数にpath、第二引数(オプション)にmodeを指定し、コールバックで結果(err)が返ってくる。

fs.access()のmodeに指定する値

デフォルトではfs.constants.F_OKとなっている。
fs.constants.F_OKは指定されたpathの存在有無しかチェックしてくれないので、権限も含めてチェックしたい場合はmodeも指定することになる。

nodejs.org - FS Constants

定数 説明
fs.constants.F_OK リソースが存在するか(読み書きの権限についてはチェックしない)
fs.constants.R_OK リソースが読み取り可能か
fs.constants.W_OK リソースが書き込み可能か
fs.constants.X_OK リソースが実行可能か(Windows環境の場合はF_OKと同じ動作となる)

今回はファイルの読み取りと書き込みが可能かをチェックしたいので、fs.access()のmodeにはfs.constants.R_OKfs.constants.W_OKをパイプ(|)でつないで、fs.constants.R_OK | fs.constants.W_OKと指定することになる。

コールバック(err)の扱い

modeで指定したチェック内容に対してエラー(存在しない、読み取り不可、書き込み不可など)がある場合、コールバックのerrに情報が詰められて返される。
err.codeに格納されたエラーコードでエラーの内容がわかる。エラーコードはLinuxのファイルシステムのエラーコードに則っているらしい。

nodejs.org - Common System Errors
Errors: Linux System Errors

err.codeの値 説明
ENOENT 指定されたリソースが存在しない
EPERM 指定されたリソースが存在するが権限が不足している
EBUSY 指定されたリソースがビジー状態(他のプロセスで使用されている)

今回はfs.constants.R_OK | fs.constants.W_OKでエラーが返された場合、フォルダが無い場合はフォルダを作成したい。
そのためerr.codeの値がENOENTの場合(指定したフォルダが存在しない場合)はfs.mkdirSync()でフォルダを作成している。

nodejs.org - fs.mkdirSync

ファイルの読み込み

ファイルの読み込みはNodeのfsモジュールに組み込まれているfs.readFile()で行う。

nodejs.org - fs.readFile

コード

index.js
const express = require('express');
const app = express();
const fs = require('fs');
const path = require('path');

// ルート設定
app.get('/', (req, res) => res.send('Hello World'));

// api-create-request-fileの設定
app.get('/api/v1/create-request-file', (req, res) =>{
    var filePath = "C:/test/request.txt"
    var dirName = path.dirname(filePath);
    fs.access(dirName, fs.constants.R_OK | fs.constants.W_OK, (err) => {
        if (err) {
            if (err.code === "ENOENT") {
                fs.mkdirSync(dirName);
                console.log("フォルダ " + dirName + " を作成しました");
            } else {
                console.log("フォルダ " + dirName + " の書き込み権限がありません");
                return res.status(500).send("エラーが発生しました");
            } 
        }

        fs.writeFile(filePath , "書き込みデータ" , (err) => {
            if(err){
                return res.status(500).send("エラーが発生しました");
            }
            else{
                return res.status(200).send("ファイルが正常に書き出しされました");
            }
        });
    });
});

// api-read-response-fileの設定
app.get('/api/v1/read-response-file', (req, res) =>{
    var filePath = "C:/test/response.txt"
    var dirName = path.dirname(filePath);
    fs.access(dirName, fs.constants.R_OK, (err) => {
        if (err) {
            if (err.code === "ENOENT") {
                console.log("フォルダ " + dirName + " が存在しません");
            } else{
                console.log("フォルダ " + dirName + " の読み取り権限がありません");
            }
            return res.status(500).send("エラーが発生しました");
        }

        fs.readFile(filePath , "utf8", (err, data) => {
            if(err){
                return res.status(500).send("エラーが発生しました");
            }
            else{
                return res.status(200).send(data);
            }
        });
    });
});

// イベント待機
app.listen(3000, () => console.log('Listening on port 3000'));

読み込むファイルの内容

response.txt
読み込みデータ

実行結果

正常に読み込めた場合

正常にファイルを読み込めた場合、ステータスコード200(正常)で読み込んだdataがHTTPレスポンスとして返される。

WS000084.JPG

正常に読み込めなかった場合

指定されたパスが無いなど、正常に読み込めなかった場合はステータスコード500(サーバエラー)がHTTPレスポンスとして返される。

WS000085.JPG

6
1
0

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
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?