반응형
05-14 05:47
Today
Total
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
관리 메뉴

개발하는 고라니

[Node.js] Node.js Tutorial (3) - File System 본문

Framework/Node.js

[Node.js] Node.js Tutorial (3) - File System

조용한고라니 2021. 4. 16. 14:48
반응형

Node.js File System 모듈

Node의 file system 모듈은 컴퓨터의 파일 시스템에서 작업하는 것을 허락한다.

File System 모듈을 추가하기 위해서는 'fs'를 require 한다

const fs = require('fs');

 

일반적으로 File System 모듈은 다음의 용도로 쓰인다.

  • 파일 읽기
  • 파일 생성하기
  • 파일 수정하기
  • 파일 삭제하기
  • 파일 이름 변경하기

# 파일 읽기

fs.readFile(path[, options], callback)

/*
path : <string> | <Buffer> | <URL> | <integer> 파일이름, 파일 명세

options : <Object> | <string>
    - encoding : (default - null)
    - flag : 아래 참고 (default - 'r')
    - signal : ???

callback : <Function>
    - err
    - <string> | <Buffer>
*/

//example
const fs = require('fs');

fs('/etc/passwd', (err, data) => {

  if (err) throw err;
  console.log(data);
});

 

※ File System Flags

a 파일을 추가(내용을 덧붙이기). 파일이 존재하지 않으면 생성
a+ 파일을 읽기/추가. 파일이 존재하지 않으면 생성
as 동기적 추가. 파일이 존재하지 않으면 생성
r 읽기로 열기. 파일이 존재하지 않으면 예외 발생
r+ 읽기/쓰기로 열기. 파일이 존재하지 않으면 예외 발생
rs+ 동기적 읽기/쓰기로 열기. 동기식 작업이 필요한 경우 openSync() 호출해야함
w 쓰기로 열기. 파일이 존재하지 않으면 생성되고, 파일이 있으면 덮어씀
w+ 읽기/쓰기로 열기. 파일이 존재하지 않으면 생성, 존재하면 덮어씀

 

브라우저에 'Hello World'가 아닌 다른 html 파일의 내용을 읽어 브라우저에 출력하는 예제를 해보도록 하자.

//first.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>이것은 HTML 코드 입니다.</h1>
    <div style="background-color: blue; width: 200px; height: 200px;"></div>
</body>
</html>
//hello.js

const http = require('http');
const url = require('url');
const fs = require('fs');

const hostname = 'localhost' //127.0.0.1
const port = 3000;

const server = http.createServer((request, response) => {
    
    let urlObj = url.parse(request.url, true);
    let qs = urlObj.query;

    fs.readFile('html/first.html', 'utf-8', function(err, data) {

        if(err) throw err;
        
        data += 'hello World';
        response.write(data);
        response.end();

        return data;
    });
});

server.listen(port, hostname, () => {
    console.log(`Server is running at http://${hostname}:${port}`);
});

위와 같이 파란 박스가 나옴을 알 수 있다. html 디렉토리 안에 first.html 파일의 내용을 읽어 브라우저에 출력해준 것이다. 단 이때 Header에 이 내용은 html이라는 것을 알려주면 좋다. 굳이 안해도 되긴 하다.

# 파일 생성

Node의 File System 모듈의 파일 생성하는 메서드는 다음과 같다.

  • fs.appendFile()
  • fs.open()
  • fs.writeFile()

fs.appendFile()

이 중에 appendFile()은 기존 파일에 이어쓰기를 해주며, 파일이 없다면 생성해준다.

fs.appendFile(path, data[, options], callback)
/*
path : 파일 경로, 파일 명세
data : 추가할 데이터
options :
    - encoding : 데이터의 인코딩
    - mode : 파일 권한
    - flag : default - a
callback : 인자로 err가 있다.
*/

//example
fs.appendFile('message.txt', 'data~~~~', 'utf-8', function(err) {
	console.log('작업 완료');
});

 

appendFile()을 이용해 html파일을 생성하고, 작성한 html 파일을 readFIle()로 읽어 브라우저에 출력해보는 예제를 다뤄보도록 하자.

현재 html 디렉토리에 first.html 밖에 없다. 이제 wAndR.js를 실행시키면 test.html이 생기게 된다.

//wAndR.js

const http = require('http');
const fs = require('fs');

const port = 3000;
const server = http.createServer((request, response) => {

    //test.html 파일에 write 할 문자열
    let html = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>HTML</h1>
        <div style="background-color: red; width: 100px; height: 100px;"></div>
    </body>
    </html>
    `;

    //html 하위에 test.html 파일을 생성하고 위에 정의한 html을 write
    fs.appendFile('html/test.html', html, 'utf-8', (err) => {
        if(err) throw err;

        console.log('작업 완료');
    });

    //html/test.html 파일을 읽어서 response 응답으로 보내는 과정
    fs.readFile('html/test.html', 'utf-8', (err, data) => {
        if(err) throw err;

        response.writeHead(200, "Content-Type", 'text/html');
        response.write(data);
        response.end();
    });

}).listen(port, () => {
    console.log(port + " is running");
});
$ node js\wAndR.js

이제 다음과 같이 새 파일이 생성되고, 브라우저에 HTML이 출력되는 것을 볼 수 있다. 다만 appendFile()은 file flag 기본 값이 'a'이기 때문에 옵션에 flag를 주지 않으면 파일을 덮어쓰는 것이 아닌 덧붙여 쓰기 때문에 html 코드가 동일하게 여러번 붙여지게 된다.

fs.open()

fs.open() 메서드는 조금 범용적인 메서드로써 다른 메서드들과는 다르게 'flag'를 반드시 두 번째 인자로 갖는다. 만약 flag가 'w'면 "쓰기"로 읽는 거라 특정 파일을 쓰는 용도로 여는 것이다. 파일이 존재하지 않는다면 빈 파일이 생성된다.

fs.open( path[, flags[, mode]], callback )
/*
path : 파일 경로
flags : (default - r)
mode : 파일의 권한 (예: 0o666 --> default) (파일을 생성할 때만 주는 옵션)
callback : 
    - err : 에러 객체
    - fd : 파일 디스크럽터
*/

//example
fs.open('html/test.html, 'r', (err, fd) => {

	
    console.log(fd);
});

 

fd가 무엇인지 찾아보았더니, fd는 fileData가 아닌 파일을 접근할 수 있는 객체이다. 즉, fs.readFile() 처럼 콜백 함수에서 그 데이터를 다루는 것이 아니라 fs.open()의 콜백함수의 인자인 fd를 이용해 fs.readFile, fs.writeFile 등을 활용해야 하는 것이다. 파일을 다 쓰고난 이후 close()를 해주자.

    fs.open('html/test.html', (err, fd) => {
        if(err) throw err;

        fs.readFile(fd, (err1, data) => {
            if(err1) throw err1;

            response.write(data);

            fs.close(fd, ()=>{
                console.log('파일을 닫습니다.');
            });
            response.end();
        });
    })

fs.writeFile()

fs.writeFile()은 만약 파일이 존재한다면 그 파일과 내용을 대체(덮어쓰기)한다. 만약 존재하지 않는다면 특정 content를 유지한체 새 파일을 생성한다.

fs.writeFile( file, data[, options], callback )

/*
file : [string / Buffer / URL / integer] 파일 이름, fd
data : [string / Buffer / TypedArray / DataView / Object] 쓸 데이터
options : 
    - encoding : 기본값 = utf8
    - mode : 기본값 = 0o666
    - flag : 기본값 = 'w'
callback : 
    - err
*/

    //example
    let html = '<h1>This is HTML</h1>';

    fs.writeFile('html/test1.html', html, (err) => {
        
        if(err) throw err;
        response.end('Write Completed');
    });

# 파일 수정

파일을 수정하는 것에 있어 다음과 같은 메서드를 가진다.

  • fs.appendFile()
  • fs.writeFile()

 

두개 다 파일을 수정할 수 있지만, 차이점이라고 하면 append는 말 그대로 뒤에 이어쓰는거고, write는 덮어쓰게 된다.

 

# 파일 삭제

파일을 삭제하기 위해서 fs.unlink() 메서드를 사용할 수 있다.

fs.unlink( path, callback )

/*
path : 파일 경로
callback : (err)
*/

//example
fs.unlink('html/test1.html', (err) => {

    if(err) throw err;
    
    console.log('html file is removed');
});

# 파일 이름 변경

파일 이름을 변경하기 위해선 fs.rename()을 사용한다.

fs.rename( oldPath, newPath, callback)

//example
fs.rename('html/test.html', 'html/newTest.html', (err) => {
    if(err) throw err;
    console.log('renamed');
});

# 파일 업로드

Node.js로 파일 업로드 또한 할 수 있다.

다만 이 모듈은 내장 모듈이 아니기 때문에 npm을 이용해 설치해야한다.

$ npm install formidable

다운로드 받은 후 마찬가지로 require해준다.

const formidable = require('formidable');

1) 업로드 폼 및 node 기본 코드 준비

파일을 업로드하기 위해 HTML의 폼 태그를 작성한다.

//fileUpload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div style="width: 500px; height: 100px; background-color: green;">
        <form action="fileUpload" method="post" enctype="multipart/form-data">
            <div>
                <input type="file" name="file" style="width: 100%;">
                <input type="submit">
            </div>
        </form>
    </div>
</body>
</html>

이를 실행시켜줄 node 서버단 코드 작성.

const formidable = require('formidable');
const http = require('http');
const url = require('url');
const fs = require('fs');

http.createServer((request, response) => {

    response.writeHead(200, "Content-Type", "text/html");
    
    fs.readFile('html/fileUpload.html', (err, data) => {
        if(err) throw err;
        response.write(data);
        response.end();
    });

    
}).listen(3000);

2) 업로드된 파일 파싱

Formidable 모듈을 포함하면 업로드된 파일을 서버에 도달하자마자 파싱할 수 있다. 파일이 업로드되고 파싱됬을 때, 임시 저장소에서 찾아볼 수 있다.

우선 form에서 파일을 서버로 POST 요청했을 때 잘 오는지를 확인 하기 위한 코드를 작성해보자.

const formidable = require('formidable');
const http = require('http');
const url = require('url');
const fs = require('fs');

http.createServer((request, response) => {

    if(request.url == '/fileUpload'){

        let form = new formidable.IncomingForm();
        form.parse(request, (err, fields, files) => {

            if(err) throw err;

            response.write('file uploaded');
            response.end();
        });
    } else {
        response.writeHead(200, "Content-Type", "text/html");
        
        fs.readFile('html/fileUpload.html', (err, data) => {
            if(err) throw err;
            response.write(data);
            response.end();
        });
    }

    
}).listen(3000);

 

위 코드를 실행하고 localhost:3000을 가면 파일 업로드 할 수 있는 창이 뜬다.

여기서 파일을 제출하면 파일이 업로드 되었다는 문구를 볼 수 있다.

3) 파일 저장하기

파일이 정상적으로 오는 것을 확인했으면 이제 로컬 저장소에 저장하는 일이 남았다.

이제 formidable 객체를 사용하면 되는데 이에 대한 설명은 잠시 후에 간단하게 해보도록 한다.

const formidable = require('formidable');
const http = require('http');
const url = require('url');
const fs = require('fs');

http.createServer((request, response) => {

    if(request.url == '/fileUpload'){

        let form = new formidable.IncomingForm();
        form.parse(request, (err, fields, files) => {

            if(err) throw err;

            let oldPath = files.file.path;
            let fileName = files.file.name;
            let newPath = 'C:/temp/datas/' + fileName; 

            fs.rename(oldPath, newPath, (err) => {

                if(err) throw err;
                response.write('file uploaded and saved');
                response.end();
            });

        });
    } else {
        response.writeHead(200, "Content-Type", "text/html");
        
        fs.readFile('html/fileUpload.html', (err, data) => {
            if(err) throw err;
            response.write(data);
            response.end();
        });
    }

    
}).listen(3000);

※ formidable

 

  • class
    • Formidable.IncomingForm : 요청 분석 클래스
    • Formidable.File : 업로드된 파일 정보
  • Event
    • field : 이름 / 값 도착 이벤트
    • file : 파일 도착 이벤트
    • aborted : 요청 중지( 클라이언트 )
    • end : 종료
  • property
    • form.uploadDir : 업로드 디렉토리 경로
    • form.keepExtension : 확장자 보존
    • form.multiples : 다중 파일 업로드
  • Body Parse
    • form.parse(request, (err, fields, files) => {})
  • Formidable.File
    • file.size
    • file.path
    • file.name
    • file.type
    • file.lastModifiedDate
    • file.has

# References

www.w3schools.com/nodejs/nodejs_uploadfiles.asp

nesoy.github.io/articles/2017-04/Nodejs-fileUpload

stackoverflow.com/questions/28953535/formidable-and-node-js-typeerror-cannot-read-property-path-of-undefined

github.com/node-formidable/formidable

 

반응형

'Framework > Node.js' 카테고리의 다른 글

[Node.js] 파일 업로드  (0) 2021.04.24
[Node.js] 요청 라우팅 - Router  (0) 2021.04.23
[Node.js] Node.js Tutorial (2)  (0) 2021.04.16
[Node.js] Node.js Tutorial (1)  (0) 2021.04.16
[Node.js] Express Middleware의 Types  (0) 2021.01.08
Comments