본문 바로가기
Python

[Python] Flask 및 jQuery를 사용하여 AJAX 파일 업로드

by daewooki 2021. 11. 21.
반응형

Flask 서버에 AJAX 및 jQuery를 사용하여 파일 업로드하는 방법을 정리합니다.

Flask 구조상 파일은 uploads 라는 폴더에 업로드 됩니다.

uploads 폴더가 있는지 확인이 필요합니다. 없으면 생성이 될 수 있도록 코드를 짜야되고요.

 

 

파일을 서버에 업로드하는 방법으로는 Form을 이용하여 제출 시 바로 전송하고 처리하는 방식도 있습니다만,

이 포스트에서는 AJAX를 이용해서 별도의 버튼을 클릭 시에 업로드될 수 있도록 하고, 전체 페이지를 새로고침 하지


Prerequisites

Python 3.7.4, Flask 1.1.1

 

Flask 애플리케이션 구성

Flask 프레임워크를 통해 애플리케이션을 구성합니다. 또한, 파일 업로드 위치와 사용자가 업로드할 수 있는 모든 파일의 최대 크기를 정의합니다.

보안상의 이유로 또는 서버 공간의 소모를 피하기 위해 사용자가 파일 크기에 제한 없이 업로드하도록 허용해서는 안 됩니다.

 

app.py 코드

from flask import Flask

UPLOAD_FOLDER = 'C:/uploads'

app = Flask(__name__)
app.secret_key = "secret key"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

HTML 템플릿 생성

파일 업로드 페이지를 렌더링 하기 위해 templates 디렉터리 아래에index.html을 작성해야합니다.

Upload 버튼을 클릭한 후 FormData 파일 데이터를 저장하는 객체를 만듭니다.

먼저 파일 수를 검색하고 각 파일을 FormData 객체에 append 시켜서 저장합니다.

마지막으로 대상 디렉터리에 업로드하기 위해 서버 측 코드가 작성된 python-flask-files-upload url로 파일 데이터를 보냅니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!doctype html>
<html>
<head>
    <title>Python Flask File(s) Upload Example</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function (e) {
            $('#upload').on('click'function () {
                var form_data = new FormData();
                var ins = document.getElementById('multiFiles').files.length;
                
                if(ins == 0) {
                    $('#msg').html('<span style="color:red">Select at least one file</span>');
                    return;
                }
                
                for (var x = 0; x < ins; x++) {
                    form_data.append("files[]"document.getElementById('multiFiles').files[x]);
                }
                
                $.ajax({
                    url: 'python-flask-files-upload'// point to server-side URL
                    dataType: 'json'// what to expect back from server
                    cache: false,
                    contentType: false,
                    processData: false,
                    data: form_data,
                    type: 'post',
                    success: function (response) { // display success response
                        $('#msg').html('');
                        $.each(response, function (key, data) {                            
                            if(key !== 'message') {
                                $('#msg').append(key + ' -> ' + data + '<br/>');
                            } else {
                                $('#msg').append(data + '<br/>');
                            }
                        })
                    },
                    error: function (response) {
                        $('#msg').html(response.message); // display error response
                    }
                });
            });
        });
    </script>
</head>
<body>
    <h2>Python Flask File(s) Upload - Select file(s) to upload</h2>
    <dl>
        <p>
            <p id="msg"></p>
            <input type="file" id="multiFiles" name="files[]" multiple="multiple"/>
            <button id="upload">Upload</button>
        </p>
    </dl>
</body>
cs

파이썬 업로드 메인 함수

AJAX를 통해 넘어온 파일을 저장하는 함수를 작성해야 합니다. 

성공 메시지 일 경우 다시 AJAX로 값을 넘겨주어야 합니다. 

만약 허용되지 않은 파일이거나 오류가 발생할 경우, 오류 메시지를 전달하여 html에 표시합니다. 

 

main.py 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import os
import urllib.request
from app import app
from flask import Flask, flash, request, redirect, render_template, jsonify
from werkzeug.utils import secure_filename
 
ALLOWED_EXTENSIONS = set(['txt''pdf''png''jpg''jpeg''gif'])
 
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.'1)[1].lower() in ALLOWED_EXTENSIONS
    
@app.route('/')
def upload_form():
    return render_template('file-upload.html')
 
@app.route('/python-flask-files-upload', methods=['POST'])
def upload_file():
    # check if the post request has the file part
    if 'files[]' not in request.files:
        resp = jsonify({'message' : 'No file part in the request'})
        resp.status_code = 400
        return resp
    
    files = request.files.getlist('files[]')
    
    errors = {}
    success = False
    
    for file in files:
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            success = True
        else:
            errors[file.filename] = 'File type is not allowed'
    
    if success and errors:
        errors['message'= 'File(s) successfully uploaded'
        resp = jsonify(errors)
        resp.status_code = 206
        return resp
    if success:
        resp = jsonify({'message' : 'Files successfully uploaded'})
        resp.status_code = 201
        return resp
    else:
        resp = jsonify(errors)
        resp.status_code = 400
        return resp
 
if __name__ == "__main__":
    app.run()
cs

Flask 애플리케이션 배포

python main.py서버를 실행합니다. 

 

애플리케이션 테스트

홈페이지

브라우저에서 URL http://localhost:5000/ 을 누르면 이미지와 같이 출력이 표시됩니다.

- 파일을 아무것도 선택하지 않고 업로드 버튼을 누르는 경우

최소 하나라도 선택해야 된다고 표시

 

- 성공

 

전체 코드는 아래 링크 참고

https://github.com/Daewooki/Python/tree/main/python-flask-ajax-file-upload

 

GitHub - Daewooki/Python

Contribute to Daewooki/Python development by creating an account on GitHub.

github.com

 

반응형

댓글