最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python使用Flask 3實現(xiàn)渲染指定目錄下Md文件

 更新時間:2026年02月24日 09:05:29   作者:belldeep  
這篇文章主要為大家詳細介紹了python如何使用Flask 3實現(xiàn)渲染指定目錄下Md文件,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

請用 python編程 : flask 3, mistune 2, python-multipart 實現(xiàn)同樣功能的Web服務

以下是使用 Flask 3 + mistune 2 + python-multipart 實現(xiàn)與 server2.js 相同功能的 Python Web 服務,完整保留了原功能并適配 Python 生態(tài):

# -*- coding: utf-8 -*-
import os
from pathlib import Path
import mimetypes
import mistune
from mistune.renderers import HTMLRenderer
from flask import Flask, request, jsonify, send_file, send_from_directory, make_response
from werkzeug.utils import secure_filename

# 初始化 Flask 應用
app = Flask(__name__, static_folder='static', static_url_path='/')

# ====================== 配置項 ======================
# 默認MD文件目錄
DEFAULT_MD_DIR = Path(__file__).parent / 'md-files'
# 確保默認目錄存在
DEFAULT_MD_DIR.mkdir(parents=True, exist_ok=True)
print(f"創(chuàng)建/使用默認MD文件目錄: {DEFAULT_MD_DIR.absolute()}")

# 允許上傳的文件類型
ALLOWED_EXTENSIONS = {'.md', '.markdown'}
# 文件大小限制 (5MB)
MAX_CONTENT_LENGTH = 5 * 1024 * 1024
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH

# ====================== 安全工具函數(shù) ======================
def validate_and_normalize_dir(dir_path: str) -> Path:
    """驗證并規(guī)范化目錄路徑"""
    # 如果為空,返回默認目錄
    if not dir_path or dir_path.strip() == '':
        return DEFAULT_MD_DIR.absolute()
    
    # 解析為絕對路徑
    abs_path = Path(dir_path.strip()).absolute()
    
    # 檢查目錄是否存在
    if not abs_path.exists():
        raise ValueError(f"目錄不存在: {abs_path}")
    
    # 檢查是否是目錄(不是文件)
    if not abs_path.is_dir():
        raise ValueError(f"不是有效的目錄: {abs_path}")
    
    # 檢查目錄是否可讀
    if not os.access(abs_path, os.R_OK):
        raise ValueError(f"沒有目錄讀取權限: {abs_path}")
    
    return abs_path

def allowed_file(filename: str) -> bool:
    """檢查文件擴展名是否合法"""
    return Path(filename).suffix.lower() in ALLOWED_EXTENSIONS

# ====================== 配置 mistune 渲染器(支持 mermaid) ======================
class MermaidRenderer(HTMLRenderer):
    """自定義渲染器,支持 mermaid 語法"""
    def block_code(self, code: str, info: str = '') -> str:
        if info and info.strip() == 'mermaid':
            return f'<div class="mermaid">[code]</div>'
        # 調(diào)用父類默認實現(xiàn)
        return super().block_code(code, info)

# 創(chuàng)建 mistune 實例
md_renderer = MermaidRenderer()
md_parser = mistune.create_markdown(renderer=md_renderer,
    plugins=['strikethrough', 'table', 'url'],
    escape=False       # 關鍵配置:禁用字符轉義
    )

# ====================== 讀取靜態(tài) HTML 模板(緩存) ======================
def get_index_html() -> str:
    """讀取并緩存 index2.html 內(nèi)容"""
    index_path = Path(__file__).parent / 'static' / 'index2.html'
    if not index_path.exists():
        raise FileNotFoundError(f"index2.html 不存在: {index_path}")
    with open(index_path, 'r', encoding='utf-8') as f:
        return f.read()

index_html = get_index_html()

# ====================== 接口:獲取MD文件列表(支持自定義目錄) ======================
@app.route('/get-md-files', methods=['GET'])
def get_md_files():
    try:
        # 獲取并驗證目錄路徑
        dir_path = validate_and_normalize_dir(request.args.get('dirPath', ''))
        
        # 讀取目錄下所有.md文件(排除隱藏文件)
        files = []
        for file in dir_path.iterdir():
            if file.is_file() and allowed_file(file.name) and not file.name.startswith('.'):
                files.append(file.name)
        
        # 按名稱排序
        files.sort()
        return jsonify(files)
    
    except ValueError as e:
        app.logger.error(f"讀取文件列表失敗: {e}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        app.logger.error(f"讀取文件列表異常: {e}")
        return jsonify({'error': f'服務器內(nèi)部錯誤: {str(e)}'}), 500

# ====================== 接口:加載指定MD文件并渲染(支持自定義目錄) ======================
@app.route('/load-md-file', methods=['GET'])
def load_md_file():
    try:
        # 驗證文件名參數(shù)
        filename = request.args.get('filename', '')
        if not filename or '..' in filename or not allowed_file(filename):
            return jsonify({'error': '無效的文件名'}), 400
        
        # 解碼文件名(處理URL編碼)
        filename = request.args.get('filename', '').encode('utf-8').decode('unicode_escape')
        
        # 獲取并驗證目錄路徑
        dir_path = validate_and_normalize_dir(request.args.get('dirPath', ''))
        file_path = dir_path / secure_filename(filename)
        
        # 檢查文件是否存在
        if not file_path.exists() or not file_path.is_file():
            return jsonify({'error': f'文件不存在: {filename}'}), 404
        
        # 檢查文件是否可讀
        if not os.access(file_path, os.R_OK):
            return jsonify({'error': f'沒有文件讀取權限: {filename}'}), 403
        
        # 讀取文件內(nèi)容并渲染為HTML
        with open(file_path, 'r', encoding='utf-8') as f:
            md_content = f.read()
        rendered_html = md_parser(md_content)
        
        return rendered_html
    
    except ValueError as e:
        app.logger.error(f"加載MD文件失敗: {e}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        app.logger.error(f"加載MD文件異常: {e}")
        return jsonify({'error': f'服務器內(nèi)部錯誤: {str(e)}'}), 500

# ====================== 原有接口 ======================
# 1. 首頁:返回上傳頁面
@app.route('/')
def index():
    return send_file(Path(__file__).parent / 'static' / 'index2.html')

# 2. 處理 Markdown 文件上傳 + 解析 + 渲染
@app.route('/upload-md', methods=['POST'])
def upload_md():
    try:
        # 檢查是否有文件上傳
        if 'mdFile' not in request.files:
            return '<h1>錯誤</h1><p>請選擇要上傳的 Markdown 文件!</p>', 400
        
        file = request.files['mdFile']
        # 檢查文件名是否為空
        if file.filename == '':
            return '<h1>錯誤</h1><p>請選擇要上傳的 Markdown 文件!</p>', 400
        
        # 檢查文件類型
        if file and allowed_file(file.filename):
            # 讀取文件內(nèi)容
            md_content = file.read().decode('utf-8')
            # 渲染為HTML
            rendered_html = md_parser(md_content)
            # 替換模板中的占位符
            final_html = index_html.replace('<div id="markdown-content"></div>', rendered_html)
            
            response = make_response(final_html)
            response.headers['Content-Type'] = 'text/html; charset=utf-8'
            return response
        
        # 文件類型不允許
        return '<h1>錯誤</h1><p>僅支持上傳 .md 或 .markdown 格式的文件!</p>', 400
    
    except Exception as e:
        app.logger.error(f"處理上傳文件出錯: {e}")
        error_html = f"""
            <h1>出錯了</h1>
            <p>處理上傳的 Markdown 文件失?。簕str(e)}</p>
            <a href="/" rel="external nofollow" >返回上傳頁面</a>
        """
        return error_html, 500

# 靜態(tài)文件服務(兼容原邏輯)
@app.route('/<path:filename>')
def serve_static(filename):
    return send_from_directory(app.static_folder, filename)

# ====================== 啟動服務 ======================
if __name__ == '__main__':
    # 注冊 mimetypes(確保js文件正確解析)
    mimetypes.add_type('application/javascript', '.js')
    
    print(f"服務已啟動:http://localhost:8000")
    print(f"默認MD文件目錄:{DEFAULT_MD_DIR.absolute()}")
    print(f"訪問 http://localhost:8000/index2.html 即可瀏覽和渲染MD文件")
    
    # 啟動Flask服務(調(diào)試模式,生產(chǎn)環(huán)境請關閉)
    app.run(host='127.0.0.1', port=8000, debug=True)

配套依賴安裝

創(chuàng)建 requirements.txt 文件:

Flask==3.0.3
mistune==2.0.5
python-multipart==0.0.6
Werkzeug==3.0.3

安裝依賴:

pip install -r requirements.txt

關鍵說明(與原 Node.js 版本對齊)

功能完全對齊

  • 支持自定義目錄加載 MD 文件列表
  • 加載并渲染指定 MD 文件(支持 Mermaid 圖表)
  • 上傳 MD 文件并實時渲染
  • 路徑安全校驗(防止路徑遍歷、權限檢查)
  • 文件類型/大小限制

核心差異適配

  • Node.js 的 markdown-it → Python 的 mistune(自定義渲染器支持 Mermaid)
  • Node.js 的 multer → Flask 原生 + python-multipart 處理文件上傳
  • Node.js 的 fs/path → Python 的 pathlib/os 處理文件系統(tǒng)
  • 錯誤處理、響應格式完全對齊原接口

部署注意事項

  • 需要保持原有的 static 目錄結構(包含 index2.htmlmermaid.min.js
  • md-files 目錄會自動創(chuàng)建,用于存放默認 MD 文件
  • 生產(chǎn)環(huán)境請關閉 debug=True,并使用 Gunicorn 等 WSGI 服務器運行

目錄結構要求

TREE /F
md-mermaid
├── server.py          # Python 服務文件
├── static/            # 靜態(tài)文件目錄
│   ├── index2.html    # 前端頁面(復用原文件)
│   └── mermaid.min.js # Mermaid 渲染腳本
├── md-files/          # 默認 MD 文件目錄(自動創(chuàng)建)
└── requirements.txt   # 依賴文件

運行方式

python server.py

訪問 http://localhost:8000 即可使用,功能與原 Node.js 版本完全一致。

以上就是python使用Flask 3實現(xiàn)渲染指定目錄下Md文件的詳細內(nèi)容,更多關于python渲染Md文件的資料請關注腳本之家其它相關文章!

相關文章

  • Python Numpy中數(shù)組的集合操作詳解

    Python Numpy中數(shù)組的集合操作詳解

    這篇文章主要為大家詳細介紹了Python Numpy中數(shù)組的一些集合操作方法,文中的示例代碼講解詳細,對我們學習Python有一定幫助,需要的可以參考一下
    2022-08-08
  • 基于python實現(xiàn)學生信息管理系統(tǒng)

    基于python實現(xiàn)學生信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了基于python學生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • java中兩個byte數(shù)組實現(xiàn)合并的示例

    java中兩個byte數(shù)組實現(xiàn)合并的示例

    今天小編就為大家分享一篇java中兩個byte數(shù)組實現(xiàn)合并的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Python刪除空文件和空文件夾的方法

    Python刪除空文件和空文件夾的方法

    這篇文章主要介紹了Python刪除空文件和空文件夾的方法,涉及Python針對文件與文件夾的遍歷、判斷與刪除等技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • python根據(jù)json數(shù)據(jù)畫疫情分布地圖的詳細代碼

    python根據(jù)json數(shù)據(jù)畫疫情分布地圖的詳細代碼

    這篇文章主要介紹了python根據(jù)json數(shù)據(jù)畫疫情分布地圖的詳細代碼,掌握使用pyecharts構建基礎的全國地圖可視化圖表,本文結合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-12-12
  • Python實現(xiàn)Tracert追蹤TTL值的方法詳解

    Python實現(xiàn)Tracert追蹤TTL值的方法詳解

    Tracert命令跟蹤路由原理是IP路由每經(jīng)過一個路由節(jié)點TTL值會減一。本文我們將通過scapy構造一個路由追蹤工具并實現(xiàn)一次追蹤,感興趣的小伙伴可以了解一下
    2022-10-10
  • python基于Tkinter實現(xiàn)人員管理系統(tǒng)

    python基于Tkinter實現(xiàn)人員管理系統(tǒng)

    這篇文章主要為大家詳細介紹了python基于Tkinter實現(xiàn)人員管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 總結Python中邏輯運算符的使用

    總結Python中邏輯運算符的使用

    這篇文章主要介紹了總結Python中邏輯運算符的使用,是Python學習當中的基礎知識,需要的朋友可以參考下
    2015-05-05
  • python爬蟲parsel-css選擇器的具體用法

    python爬蟲parsel-css選擇器的具體用法

    本文主要介紹了python爬蟲parsel-css選擇器的具體用法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • Flask入門教程實例:搭建一個靜態(tài)博客

    Flask入門教程實例:搭建一個靜態(tài)博客

    這篇文章主要介紹了Flask入門教程實例:搭建一個靜態(tài)博客,本文主要介紹flask框架的環(huán)境配置以及一個靜態(tài)博客胡搭建實例,需要的朋友可以參考下
    2015-03-03

最新評論

青海省| 建宁县| 阳城县| 奇台县| 华坪县| 图木舒克市| 青阳县| 墨脱县| 哈巴河县| 西林县| 工布江达县| 贺兰县| 新源县| 武城县| 丹寨县| 南阳市| 仙桃市| 从化市| 正宁县| 喀喇沁旗| 仁怀市| 泰和县| 涡阳县| 万盛区| 泸定县| 昌黎县| 饶阳县| 萨迦县| 于田县| 沙田区| 金溪县| 交城县| 镇巴县| 威海市| 杭州市| 酒泉市| 庆元县| 平利县| 松溪县| 清水县| 奎屯市|