[Python] .getctime(), request.form.list(), zipfile.ZipFile()

공부한 내용 정리하는 공간입니다.

틀린 내용이 있을 수 있습니다.

모든 지적, 첨언 환영합니다.

오늘의 코드

1. 특정 폴더의 파일 목록 웹에 표시

2. 사용자가 웹에서 선택한 파일 압축

3. 사용자에게 압축 파일 제공

from flask import Flask, render_template, request, send_file
import os
from datetime import datetime
import zipfile

app = Flask(__name__)

@app.route("/", methods=['GET', 'POST'])
def list():
    UPLOAD_PATH = "uploads"
    files = []

    for file in os.listdir(UPLOAD_PATH):
        file_path = os.path.join(UPLOAD_PATH, file)
        file_size = os.path.getsize(file_path)
        file_ctime = datetime.fromtimestamp(os.path.getctime(file_path)).strftime('%Y-%m-%d %H:%M:%S')
        files.append((file, file_size, file_ctime, file_path))
    print(files)
    return render_template('list.html', files=files)

@app.route("/compress", methods=['GET', 'POST'])
def compress():
    UPLOAD_PATH = "uploads"
    files = request.form.getlist("files")
    zip_path = os.path.join(UPLOAD_PATH, "compress.zip")

    with zipfile.ZipFile(zip_path, "w") as zip_file:
        for file in files:
            file_path = os.path.join(UPLOAD_PATH, file)
            zip_file.write(file_path, file)

    return send_file(zip_path, as_attachment=True)

if __name__ == '__main__':
    app.run(debug=True)

list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
    <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
</head>
<body>
    <form method="post" action="{{url_for('compress')}}">
    <table border="1">
        <tr>
            <td>파일 이름</td>
            <td>파일 크기</td>
            <td>파일 수정 날짜</td>
            <td>파일 경로</td>
            <td>파일 선택</td>
        </tr>
        {% for file in files %}
        <tr>
            <td>{{file[0]}}</td>
            <td>{{file[1]}}</td>
            <td>{{file[2]}}</td>
            <td>{{file[3]}}</td>
            <td><input type="checkbox" name="files" value="{{file[0]}}"></td>
        </tr>
        {% endfor %}
    </table>
    <input type="submit" value="파일 압축하기">
    </form>
</body>
</html>

 


datetime.fromtimestamp(os.path.getctime(파일경로)).strftime('%Y-%m-%d %H:%M:%S')

파일 생성 시간(ctime)을 가져와서 사람이 읽을 수 있는 형식으로 변환

datetime.fromtimestamp : 타임스탬프 값을 python의 datetime 객체로 변환, 사람이 읽을 수 있음

os.path.getctime(파일경로) : '파일 경로'의 생성 시간을 UNIX 타임스탬프 형식으로 반환, 사람이 읽을 수 없음

.strftime('%Y-%m-%d %H:%M:%S') : datetime 객체를 특정 혁식의 문자열로 변환, 사람이 읽을 수 있음

 


request.form.list()

HTML 폼 데이터를 리스트 형태로 가져올 때 사용

여러 개의 값을 하나로 가져올 때 유용함

 


zipfile.ZipFile(파일의 온전한 경로, 모드)

ZIP 파일을 생성하거나 읽고, 파일을 추가하거나 추출할 때 사용

with as문으로 사용할 경우 with문이 끝나면 자동으로 파일을 닫음

 


zipfile.ZipFile 객체.write(파일의 온전한 경로, zip안에서 표시될 이름)

지정된 파일을 ZIP 파일에 추가

ZIP 파일이 쓰기모드로 열려있어야 파일을 추가할 수 있음

'파일의 온전한 경로'는 절대경로일 수 있지만, 'zip안에서 표시될 이름'은 ZIP 내부에 상대경로로 저장

'zip안에서 표시될 이름'은 경로를 포함할 수 있음

 


오늘의 코드

1. 특정 폴더의 파일 목록 웹에 표시

2. 사용자가 웹에서 선택한 파일 압축

3. 사용자에게 압축 파일 제공

from flask import Flask, render_template, request, send_file
import os
from datetime import datetime
import zipfile

app = Flask(__name__)

@app.route("/", methods=['GET', 'POST'])
def list():
    UPLOAD_PATH = "uploads"
    files = []

    for file in os.listdir(UPLOAD_PATH):
        file_path = os.path.join(UPLOAD_PATH, file)
        file_size = os.path.getsize(file_path)
        file_ctime = datetime.fromtimestamp(os.path.getctime(file_path)).strftime('%Y-%m-%d %H:%M:%S')
        files.append((file, file_size, file_ctime, file_path))
    print(files)
    return render_template('list.html', files=files)

@app.route("/compress", methods=['GET', 'POST'])
def compress():
    UPLOAD_PATH = "uploads"
    files = request.form.getlist("files")
    zip_path = os.path.join(UPLOAD_PATH, "compress.zip")

    with zipfile.ZipFile(zip_path, "w") as zip_file:
        for file in files:
            file_path = os.path.join(UPLOAD_PATH, file)
            zip_file.write(file_path, file)

    return send_file(zip_path, as_attachment=True)

if __name__ == '__main__':
    app.run(debug=True)

list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
    <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
</head>
<body>
    <form method="post" action="{{url_for('compress')}}">
    <table border="1">
        <tr>
            <td>파일 이름</td>
            <td>파일 크기</td>
            <td>파일 수정 날짜</td>
            <td>파일 경로</td>
            <td>파일 선택</td>
        </tr>
        {% for file in files %}
        <tr>
            <td>{{file[0]}}</td>
            <td>{{file[1]}}</td>
            <td>{{file[2]}}</td>
            <td>{{file[3]}}</td>
            <td><input type="checkbox" name="files" value="{{file[0]}}"></td>
        </tr>
        {% endfor %}
    </table>
    <input type="submit" value="파일 압축하기">
    </form>
</body>
</html>

 

오늘의 코드 설명

1. 특정 폴더의 파일 목록 웹에 표시

file_ctime = datetime.fromtimestamp(os.path.getctime(file_path)).strftime('%Y-%m-%d %H:%M:%S')

file_path=os.path.join(UPLOAD_PATH, file)=경로 uploads와 uploads에 있는 파일 이름으로 만든 온전한 경로

file_path에 있는 파일의 생성 시간을 file_ctime에 저장

files.append((file, file_size, file_ctime, file_path))

file, file_size, file_ctime, file_path를 하나의 튜플로 묶어서 리스트 files에 저장

2. 사용자가 웹에서 선택한 파일 압축

files = request.form.getlist("files")

name 속성이 files인 form 데이터를 가져와서 리스트 형태로 files에 저장

    > name 속성이 files인 form은 list.html에 있는 <input> 태그

    >list.html의 <form> 태그는 서버에 있는 이름이 compress인 라우터에 POST 요청을 보냄

zip_path = os.path.join(UPLOAD_PATH, "compress.zip")

UPLOAD_PATH와 compress.zip을 결합하여 하나의 온전한 경로를 zip_path에 저장

    >UPLOAD_PATH=uploads

    >zip_path=uploads/compress.zip

with zipfile.ZipFile(zip_path, "w") as zip_file:

uploads/compress.zip을 쓰기 모드로 열어서 zip_file에 저장

with 문이 끝나면 zip파일을 자동으로 닫음

for file in files:

file은 list.html의 <input>태그에서 가져온 데이터를 저장한 리스트 files를 순회

file_path = os.path.join(UPLOAD_PATH, file)

리스트에 있는 각 파일 이름(file)과 경로(UPLOAD_PATH)를 조합해서 온전한 경로를 만들어 file_path에 저장

zip_file.write(file_path, file)

file_path에 있는 파일을 원래 파일 이름(file)으로 ZIP 파일에 추가

3. 사용자에게 압축 파일 제공

return send_file(zip_path, as_attachment=True)

uploads/compress.zip 파일을 웹 브라우저에 전송하고 사용자에게 다운로드 자동 진행

 


list.html

<form method="post" action="{{url_for('compress')}}">

서버에 이름이 compress인 라우터에 post 요청을 보냄

<input type="checkbox" name="files" value="{{file[0]}}">

사용자가 여러 선택 항목 중에서 하나 이상의 항목을 선택할 수 있도록 체크박스를 생성

체크박스가 선택되었을 때 서버로 file[0]의 값을 보냄