nginx配置尝试

news2025/2/23 12:51:15
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import JSONResponse, FileResponse, HTMLResponse
import logging
import os
from datetime import datetime
import uvicorn

# 初始化日志
logging.basicConfig(filename='file_server.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

script_dir = os.path.dirname(os.path.abspath(__file__))
pro_dir = os.path.abspath(os.path.join(script_dir, '..'))
dir_upload = os.path.abspath(os.path.join(pro_dir, 'files'))

app = FastAPI()

@app.post("/upload_file/")
async def upload_file(file: UploadFile = File(...)):
    """
    接收上传的文件,保存到服务器,并返回文件信息。
    """
    # 验证文件格式
    if file.content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
        raise HTTPException(status_code=400, detail="上传文件格式不符合要求")

    try:
        # 读取文件的二进制内容
        file_content = await file.read()

        # 调用save_upload_file函数保存文件
        file_info = await save_upload_file(dir_upload, file_content)
        if file_info is not None:
            # 如果文件保存成功,则返回文件信息
            return JSONResponse(content=file_info)
        else:
            # 文件保存失败,返回错误信息
            return JSONResponse(content={"message": "文件保存失败"}, status_code=500)
    except Exception as e:
        logger.error("文件上传错误: %s", str(e))
        return JSONResponse(content={"message": "文件上传失败"}, status_code=500)

# 定义并实现文件保存函数
async def save_upload_file(dir_upload, file_content) -> dict:
    try:
        # 确保上传目录存在
        if not os.path.exists(dir_upload):
            os.makedirs(dir_upload)

        # 使用当前时间戳生成文件名
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        file_name = f"{timestamp}.xlsx"
        file_path = os.path.join(dir_upload, file_name)

        # 保存文件到指定路径
        with open(file_path, "wb") as f:
            f.write(file_content)
        file_size = os.path.getsize(file_path)

        return {
            "file_name": file_name,
            "file_path": file_path,
            "file_size": file_size
        }
    except Exception as e:
        logger.error("文件保存失败: %s", str(e))
        return None

@app.get("/get_file/", summary="get file", tags=['文件'])
async def get_file(file_name: str):
    """
    根据文件名提供文件的 HTTP 服务
    """
    try:
        file_path = os.path.join(dir_upload, file_name)
        if not os.path.exists(file_path):
            return JSONResponse(content={"message": "文件未找到"}, status_code=404)
        return FileResponse(file_path, media_type="application/octet-stream", filename=file_name)
    except Exception as e:
        logger.error("文件下载错误: %s", str(e))
        return JSONResponse(content={"message": str(e)}, status_code=500)

@app.get("/list_files/", response_class=HTMLResponse)
async def list_files():
    """
    提供文件列表的 HTML 页面和文件上传功能
    """
    try:
        files = sorted(
            (f for f in os.listdir(dir_upload) if os.path.isfile(os.path.join(dir_upload, f))),
            key=lambda f: os.path.getmtime(os.path.join(dir_upload, f)),
            reverse=True
        )

        if not files:
            files_html = "<h2>没有可下载的文件</h2>"
        else:
            file_links = [f'<li><a href="/get_file/?file_name={file}">{file}</a></li>' for file in files]
            files_html = f"<ul>{''.join(file_links)}</ul>"

        html_content = f"""
        <html>
            <head>
                <title>文件列表和上传</title>
                <script>
                    async function uploadFile(event) {{
                        event.preventDefault();
                        const formData = new FormData();
                        const fileField = document.querySelector('input[type="file"]');

                        formData.append('file', fileField.files[0]);

                        const response = await fetch('/upload_file/', {{
                            method: 'POST',
                            body: formData
                        }});

                        const result = await response.json();
                        alert(result.message || '文件上传成功');
                        window.location.reload();
                    }}
                </script>
            </head>
            <body>
                <h1>文件列表和上传</h1>
                <form onsubmit="uploadFile(event)">
                    <input type="file" name="file" accept=".xlsx" required>
                    <button type="submit">上传文件</button>
                </form>
                <h2>文件列表</h2>
                {files_html}
            </body>
        </html>
        """
        return HTMLResponse(content=html_content)
    except Exception as e:
        logger.error("文件列表生成错误: %s", str(e))
        return HTMLResponse(content=f"<h2>错误: {str(e)}</h2>", status_code=500)

if __name__ == "__main__":
    ## 线上模式
    # uvicorn.run("file_server:app", host="0.0.0.0", port=1300)

    ## debug 模式
    uvicorn.run("file_server:app", host="0.0.0.0", port=1300, reload=True)

运行上述代码,打开http://127.0.0.1:1300/docs#/


接下来配置nginx文件

user _www;
worker_processes auto;
error_log /opt/homebrew/var/log/nginx/error.log;
pid /System/Volumes/Data/opt/homebrew/var/run/nginx.pid;

# Events
events {
    worker_connections 1024;
}

http {
    include /opt/homebrew/etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /opt/homebrew/var/log/nginx/access.log main;

    sendfile on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    gzip on;

    server {
        listen 81;
        server_name localhost;

        location /file/ {
            proxy_pass http://127.0.0.1:1300/upload_file/;
        }

        location /get_file/ {
            proxy_pass http://127.0.0.1:1300/get_file/;
        }

        location /list_files/ {
            proxy_pass http://127.0.0.1:1300/list_files/;
        }
    }
}

接下来:

访问http://127.0.0.1:81/list_files/   http://127.0.0.1:1300/list_files/ 均可以打开对应网站

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1902397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习之保存与加载

前言 模型的数据需要存储和加载&#xff0c;这节介绍存储和加载的方式方法。 存和加载模型权重 保存模型使用save_checkpoint接口&#xff0c;传入网络和指定的保存路径&#xff0c;要加载模型权重&#xff0c;需要先创建相同模型的实例&#xff0c;然后使用load_checkpoint…

Redis基础教程(十三):Redis lua脚本

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

vue3【提效】使用 VueUse 高效开发(工具库 @vueuse/core + 新增的组件库 @vueuse/components)

Vueuse 是一个功能强大的 Vue.js 生态系统工具库&#xff0c;提供了可重用的组件和函数&#xff0c;帮助开发者更轻松地构建复杂的应用程序。 官网 &#xff1a;https://vueuse.org/core/useWindowScroll/ 安装 VueUse npm i vueuse/core vueuse/components&#xff08;可选&a…

VideoAgent——使用大规模语言模型作为代理来理解长视频

概述 论文地址&#xff1a;https://arxiv.org/pdf/2403.10517 本研究引入了一个新颖的基于代理的系统&#xff0c;名为 VideoAgent。该系统以大规模语言模型为核心&#xff0c;负责识别关键信息以回答问题和编辑视频。VideoAgent 在具有挑战性的 EgoSchema 和 NExT-QA 基准上进…

讲个SystemVerilog随机约束小坑

正文 记录个在写SystemVerilog随机约束时遇到的一个小坑&#xff0c;如果没有认真去查看随机结果是否符合预期&#xff0c;还真不容易发现。 为了方便讲述&#xff0c;写了如下示例代码。类cl_a里有个随机变量aa&#xff0c;初始值为222。在module top里对类cl_a例化并进行约…

释放区块链数据科学的力量

如今&#xff0c;区块链技术和数据科学是两项最先进、最不可预测的技术。数据科学已被证明可以使用区块链技术作为原始数据源来了解有关系统运行的信息。 通过将区块链技术与数据科学相结合&#xff0c;软件开发、金融和其他领域的创造性改进已经成为可能。 在本文中&#xf…

【HTML】-解决页面内容无法选择、复制问题

目录 1、网页内容无法选中 1.1、问题原因 1.2、解决脚本 1.2.1、开启控制台窗口 1.2.2、执行脚本命令 2、内容复制弹出阻止框 2.2、解决脚本 1、网页内容无法选中 1.1、问题原因 今天在访问某一网站平台&#xff0c;需要将内容进行选择、复制时发现不可使用。 在使用…

MATLAB-分类CPO-RF-Adaboost冠豪猪优化器(CPO)优化RF随机森林结合Adaboost分类预测(二分类及多分类)

MATLAB-分类CPO-RF-Adaboost冠豪猪优化器&#xff08;CPO&#xff09;优化RF随机森林结合Adaboost分类预测&#xff08;二分类及多分类&#xff09; 分类CPO-RF-Adaboost冠豪猪优化器&#xff08;CPO&#xff09;优化RF随机森林结合Adaboost分类预测&#xff08;二分类及多分类…

[Vite]Vite插件生命周期了解

[Vite]Vite插件生命周期了解 Chunk和Bundle的概念 Chunk&#xff1a; 在 Vite 中&#xff0c;chunk 通常指的是应用程序中的一个代码片段&#xff0c;它是通过 Rollup 或其他打包工具在构建过程中生成的。每个 chunk 通常包含应用程序的一部分逻辑&#xff0c;可能是一个路由视…

公务员考试、事业编考试、教师资格证、面试、K12资料、电子书

点击上方△腾阳 关注 作者 l 腾阳 转载请联系授权 你好&#xff0c;我是腾阳。 在这个自媒体的海洋里&#xff0c;我曾是一只迷失方向的小鸟&#xff0c;多次尝试飞翔却总是跌跌撞撞。 但每一次跌倒&#xff0c;都让我更坚定地相信&#xff0c;只要不放弃&#xff0c;总…

---java KMP算法---

对于在一段字符串中查找一段字符串&#xff0c;如果用数组遍历的方法那就效率低下&#xff0c;所以产生了效率更高的KMP算法 KMP算法查只需要遍历一次字符串就可以找出第一次出现的目标字符串 要学的话建议区b站看视频&#xff0c;学着由视频学者比较容易 我这里就提供下我实…

html的作业

目录 作业题目 1.用户注册 A图 B代码 2.工商银行电子汇款单 A图 B代码 3.李白诗词 A图 B代码 4.豆瓣电影 A图 B代码 学习产出&#xff1a; 作业题目 1.用户注册 A图 B代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset&qu…

rider使用libman

问题 rider没有libman的相关功能&#xff0c;需要使用cli 安装Libman dotnet tool install -g Microsoft.Web.LibraryManager.Cli # 如果存在可以尝试更新 dotnet tool update -g Microsoft.Web.LibraryManager.Cli查看命令 libman --help初始化 cdnjs官网 libman init安…

记录excel表生成一列按七天一个周期的方法

使用excel生成每七天一个周期的列。如下图所示&#xff1a; 针对第一列的生成办法&#xff0c;使用如下函数&#xff1a; TEXT(DATE(2024,1,1)(ROW()-2)*7,"yyyy/m/d")&" - "&TEXT(DATE(2024,1,1)(ROW()-1)*7-1,"yyyy/m/d") 特此记录。…

【PWN · ret2shellcode | sandbox-bypass | 格式化字符串】[2024CISCN · 华东北赛区]pwn1_

一道栈ret2shellcodesandbox&#xff08;seccomp&#xff09;格式化字符串的题目 前言 ret2shellcode&#xff0c;已经不是简单的放到栈上、ret这样一个简单的过程。套一层seccomp的沙箱&#xff0c;打ORW又遇到open受限等等&#xff0c;考虑的蛮多。过程中收获最多的可以说是…

Codeforces Round 903 (Div. 3)A~F

A.Dont Try to Count 输入样例&#xff1a; 12 1 5 a aaaaa 5 5 eforc force 2 5 ab ababa 3 5 aba ababa 4 3 babb bbb 5 1 aaaaa a 4 2 aabb ba 2 8 bk kbkbkbkb 12 2 fjdgmujlcont tf 2 2 aa aa 3 5 abb babba 1 19 m mmmmmmmmmmmmmmmmmmm输出样例&#xff1a; 3 1 2 -1 1 0…

密码学及其应用 —— 密码学的经典问题

1. 古典密码学问题 1.1 问题1&#xff1a;破解凯撒密码 1.1.1 问题 凯撒密码是最简单的单字母替换加密方案。这是一种通过将字母表中的字母固定向右移动几位来实现的加密方法。解密下面的文本&#xff0c;该文本通过对一个去除了空格的法语文本应用凯撒密码获得&#xff1a; …

IDEA越用越卡?教你轻松解决IDEA内存占用过高问题

大家好&#xff0c;我是瑶山&#xff0c;最近IDEA越用越卡了&#xff0c;刚刚内存卡爆&#xff0c;带着整个电脑也卡的飞起&#xff0c;只能重启了电脑。 虽然重启后又恢复到了流畅&#xff0c;但是问题还是如鲠在喉&#xff0c;痛定思痛&#xff0c;还是决定处理下&#xff01…

Debezium报错处理系列之第110篇: ERROR Error during binlog processing.Access denied

Debezium报错处理系列之第110篇:ERROR Error during binlog processing. Last offset stored = null, binlog reader near position = /4 Access denied; you need at least one of the REPLICATION SLAVE privilege for this operation 一、完整报错二、错误原因三、解决方法…

JVM原理(十七):JVM虚拟机即时编译器详解

编译器无论在何时、在何种状态下把Class文件转换成与本地基础设施相关的二进制机器码&#xff0c;他都可以视为整个编译过程的后端。 后端编译器编译性能的好坏、代码优化质量的高低却是衡量一款商用虛拟机优秀与否的关键指标之一。 1. 即时编译器 即时编译器是一个把Java的…