天天看點

Python Web架構(flask,tornado)之檔案上傳

一、Flask上傳檔案

1、一個 <form> 标簽被标記有 enctype=multipart/form-data ,并且在裡面包含一個 <input type=file> 标簽。

2、服務端應用通過請求對象上的 files 字典通路檔案。

3、使用檔案的 save() 方法将檔案永久地儲存在檔案系統上的某處。

UPLOAD_FOLDER 是我們儲存上傳的檔案的地方,而 ALLOWED_EXTENSIONS 則是允許的檔案類型的集合。然後我們手動為應用添加一個的 URL 規則。我們通常很少這樣做,但是為什麼這裡要如此呢?原因是我們希望實際部署的伺服器 (或者我們的開發伺服器)來為我們提供這些檔案的通路服務,是以我們隻需要一個規則用來生成指向這些檔案的 URL 。

import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename

UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
           

下一步,就是檢查檔案類型是否有效、上傳通過檢查的檔案、以及将使用者重定向到已經上傳好的檔案 URL 處的函數了:

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['file'] # 獲得檔案  request.files['file'].read() 獲得檔案内容
        if file and allowed_file(file.filename): #file.filename 獲得檔案内容
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect(url_for('uploaded_file',filename=filename))
    return ''
           

二、Tornado上傳檔案

1、簡單的上傳檔案

ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

@url(r'/file/upload')
class FileUploadHandler(LoginedRequestHandler):
    """檔案上傳"""
    def post(self):
        data = self.request.files['file'][0]
        filename = data.get('filename')
        body = data.get('body')
        if allowed_file:
            self.write(dict(status=False, msg='請上傳正确格式'))
        else:
            body = body.decode().strip()
            self.write(dict(status=True, result=body))
           

 2、上傳圖檔

def post(self, *args, **kwargs):
        status = self.get_argument('status',None)
        size = int(self.request.headers.get('Content-Length'))
        if size / 1000.0 > 2000:
            self.set_status(400)
            self.write(dict(msg="上傳圖檔不能大于2M"))
            return
        file_info = self.request.files['file'][0]
        file_name = generate_file_name(file_info['filename'])
        if not file_name:
            self.write(dict(code=-1, msg=Invalid file name))
            return
        year_month, day = time.strftime("%Y%m"), time.strftime("%d")
        path = os.path.join(FILE_UPLOAD_PATH, year_month, day)
        # 大圖
        absolute_path = os.path.join(path, file_name)
        app_path = absolute_path[absolute_path.rindex('upload'):]
        # 縮略圖
        crop_absolute_path = os.path.join(path, 'crop'+file_name)
        crop_app_path = crop_absolute_path[crop_absolute_path.rindex('upload'):]

        self.create_dir(path)
        try:
            with open(absolute_path, 'wb') as f:
                f.write(file_info['body'])
                if status:
                    from utils import crop_image
                    crop_image(crop_absolute_path, status)
                self.write(dict(path= app_path,crop_path=crop_app_path))
        except Exception as e:
            app_log.error(e)
            raise HTTPError(500)
           

繼續閱讀