3.8 node处理formData请求

本文档展示了如何使用Node.js处理文件目录,循环发送formData请求,并编写测试脚本来验证接口响应。主要涉及模块包括fs、path、axios、FormData等,以及测试框架jest的使用。测试过程中,对文件名进行特殊字符替换并进行断言判断,确保接口返回结果与预期相符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、工作中需要发送formData请求,循环发送某个目录下的所有文件,再通过其他接口获取结果,所以先要提取文件

//parse_file.js
const fs = require('fs');
const path = require('path');
var temp = []
exports.parse_file =
    function parse_file(dir_path) {
        let p = path.join(dir_path);
        let stat = fs.lstatSync(p);
        let is_direc = stat.isDirectory();
        if (is_direc) {
            let length = fs.readdirSync(p)
            for (let i of length) {
                parse_file(path.join(dir_path + '\\' + i))
            }
        } else {
            temp.push(p)
        }
        return temp

    }

二、编写测试脚本,循环发送formData请求

//check_file.js
const parse = require('../utils/parse_file.js')
const path = require('../config/config')
const axios = require('axios')
const defaultSettings = require('../config/config')
const FormData = require('form-data');
const fs = require('fs');
const replace = require('../utils/replace')
const assert = require('assert')
axios.defaults.baseURL = defaultSettings.config.url;
// require('events').EventEmitter.defaultMaxListeners = 0;
describe('check_file', function () {
    const array = parse.parse_file(path.config.path);
    const config = {
        method: 'post',
        url: defaultSettings.config.inter_path.task,
        headers: {
            'Authorization': '',
            'cookie': '',
            'content-type': '',
        },
//有的文件会比较大的话,需要设置maxBodyLength参数
        maxBodyLength: 1000000000

    }
    beforeAll(async function () {
        await axios.post(defaultSettings.config.inter_path.dologin, defaultSettings.config.login_config, {
            headers: {
                'content-type': 'application/json;charset=UTF-8'
            }
        })
            .then(res => {
                config.headers.Authorization = res.headers["set-cookie"];
                config.headers.cookie = res.headers['set-cookie'][0];
            })
    })


    for (let i = 0; i < array.length; i++) {
        let data = new FormData();
        config.headers["content-type"] = {...data.getHeaders()}['content-type']
//将文件名当成用例名,输出到测试报告中,以对比结果,方便找出具体哪个文件没通过测试
        it(`${array[i]}`, async function () {
            let source_name;
//这里需要对replace方法中的参数判空,不然会报cannot read property 'replace' of null错误
            if (array[i] != null) {
                source_name = replace(array[i]);
            }
            jest.setTimeout(100000)
            data.append('file', fs.createReadStream(array[i]));
            data.append('remark', '');
            data.append('securityLevel', '');
            config.data = data;
            await axios(config)
                .then(function (response) {
//请求成功后,会将文件的名字给返回来,所以这里做了正则匹配,来判定接口是否成功
                    let res_name
                    if (response.data.name != null) {
                        res_name = replace(response.data.name);

                    }
                    if (new RegExp(res_name).test(source_name)) {
                        assert.ok("success")
                    } else {
                        assert.fail(`${response.data.name} don't match source's name`)
                    }

                })
                .catch(function (error) {
                    assert.fail(error)
                });

        })

    }
})

三、封装正则方法

//replace.js
//这里要对文件名中的特殊字符做个替换
module.exports = function replace(str) {
    let pattern = /[\+\-\!\@\#\$\%\^\&\*\(\)\{\}\[\]\_\=\`\~\/\\\,\.\:\;\"\'\?\。\|\,\<\>]/g;
    return str.replace(new RegExp(pattern), '')
}

四、测试报告展示

 

<think>嗯,用户问的是如何将模型部署到Web上,我需要详细解释这个过程。之前他们可能已经训练好了模型,现在想实际应用起来。首先,我需要考虑用户可能的背景,他们可能是开发者,但可能对部署流程不熟悉,需要一步步指导。 用户之前的历史显示他们刚完成模型训练,所以现在需要部署的步骤。我需要覆盖常见的部署方法,比如使用Flask或FastAPI构建API,处理输入输出,还要考虑性能优化,比如模型转换和缓存。 可能用户需要知道如何将模型集成到Web框架中,如何处理请求,以及如何确保性能和可扩展性。还要注意模型格式转换,比如保存为HDF5或使用ONNX,以及部署到生产环境时的注意事项,比如使用Gunicorn或Docker。 另外,用户可能关心前后端如何交互,比如前端如何发送请求并显示结果。需要给出代码示例,比如Flask的简单应用,和JavaScript的调用示例,这样用户可以直接参考使用。 还要提到部署后的监控和维护,比如日志记录和性能监控,这样用户知道后续如何维护他们的服务。可能还需要比较不同的部署方案,比如云服务的选择,或者使用服务器less架构,但根据用户之前的回答,他们提到了Flask和TensorFlow,所以应该以传统Web服务框架为主。 需要注意安全性和错误处理,比如文件上传的验证和防止恶意请求,这也是实际部署中常见的问题。最后,要总结关键步骤,确保用户有清晰的流程可以遵循。</think>以下分阶段详细说明模型Web部署的核心流程及具体实现方法: --- ### **一、模型准备阶段** #### 1. 格式转换(关键步骤) ```python # 保存完整模型(含权重和结构) model.save(&#39;flower_model.h5&#39;) # HDF5格式 # 或转换为轻量格式(TFLite示例) import tensorflow as tf converter = tf.lite.TFLiteConverter.from_keras_model(model) tflite_model = converter.convert() open("model.tflite", "wb").write(tflite_model) ``` **格式对比**: | 格式 | 加载速度 | 文件大小 | 适用场景 | |------------|----------|----------|----------------| | HDF5 | 快 | 较大 | 服务端部署 | | TFLite | 较快 | 小 | 移动端/嵌入式 | | ONNX | 中等 | 中等 | 跨框架部署 | --- ### **二、服务端构建** #### 1. 基础Web框架搭建(Flask示例) ```python from flask import Flask, request, jsonify import numpy as np from PIL import Image import tensorflow as tf app = Flask(__name__) model = tf.keras.models.load_model(&#39;flower_model.h5&#39;) # 加载模型 @app.route(&#39;/predict&#39;, methods=[&#39;POST&#39;]) def predict(): # 接收图片并预处理 file = request.files[&#39;image&#39;] img = Image.open(file.stream).resize((224,224)) img_array = np.expand_dims(np.array(img)/255.0, axis=0) # 推理预测 predictions = model.predict(img_array) class_idx = np.argmax(predictions[0]) return jsonify({&#39;class&#39;: class_idx, &#39;confidence&#39;: float(predictions[0][class_idx])}) if __name__ == &#39;__main__&#39;: app.run(host=&#39;0.0.0.0&#39;, port=5000) ``` #### 2. 高性能优化方案 ```python # 添加缓存和批处理 from functools import lru_cache @lru_cache(maxsize=1) # 保持模型常驻内存 def load_model(): return tf.keras.models.load_model(&#39;flower_model.h5&#39;) # 启用批处理(调整predict方法) batch_size = 32 img_batch = np.stack([preprocess(i) for i in images]) predictions = model.predict(img_batch) # 比单次预测快5-8倍 ``` --- ### **三、前端交互实现** #### 1. 基础调用示例(JavaScript) ```javascript // 图片上传预测 async function predict() { const file = document.getElementById(&#39;upload&#39;).files[0]; const formData = new FormData(); formData.append(&#39;image&#39;, file); const response = await fetch(&#39;http://your-domain/predict&#39;, { method: &#39;POST&#39;, body: formData }); const result = await response.json(); document.getElementById(&#39;result&#39;).innerHTML = `类别: ${result.class} (置信度: ${(result.confidence * 100).toFixed(1)}%)`; } ``` #### 2. 可视化增强方案 ```html <!-- 添加实时预览 --> <img id="preview" style="max-width: 300px;"> <input type="file" onchange="previewImage(event)"> <script> function previewImage(event) { const reader = new FileReader(); reader.onload = function() { document.getElementById(&#39;preview&#39;).src = reader.result; } reader.readAsDataURL(event.target.files[0]); } </script> ``` --- ### **四、生产环境部署** #### 1. 服务强化配置 ```bash # 使用Gunicorn替代Flask内置服务器 gunicorn -w 4 -b 0.0.0.0:5000 app:app # 4个工作进程 # 添加Nginx反向代理配置示例 location /predict { proxy_pass http://localhost:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } ``` #### 2. 容器化部署(Docker示例) ```dockerfile FROM python:3.8-slim RUN pip install flask tensorflow-cpu gunicorn COPY . /app WORKDIR /app CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"] ``` **性能对比**: | 部署方式 | 请求处理量 | 启动时间 | 内存消耗 | |----------------|------------|----------|----------| | Flask内置 | 50 req/s | 1s | 800MB | | Gunicorn | 200 req/s | 3s | 1.2GB | | Docker集群 | 1000+ req/s| 10s | 2GB/node | --- ### **五、安全增强措施** #### 1. 输入验证 ```python # 文件类型校验 ALLOWED_EXTENSIONS = {&#39;png&#39;, &#39;jpg&#39;, &#39;jpeg&#39;} def allowed_file(filename): return &#39;.&#39; in filename and \ filename.rsplit(&#39;.&#39;, 1)[1].lower() in ALLOWED_EXTENSIONS # 在预测方法中添加校验 if not allowed_file(file.filename): return jsonify({&#39;error&#39;: &#39;仅支持PNG/JPG格式&#39;}), 400 ``` #### 2. 速率限制 ```python # 使用Flask-Limiter扩展 from flask_limiter import Limiter limiter = Limiter(app=app, key_func=lambda: request.remote_addr) @app.route(&#39;/predict&#39;) @limiter.limit("10/minute") # 每分钟10次请求 def predict(): ... ``` --- ### **六、监控与维护** #### 1. 日志记录配置 ```python import logging from logging.handlers import RotatingFileHandler # 创建200MB循环日志 file_handler = RotatingFileHandler(&#39;app.log&#39;, maxBytes=200*1024*1024, backupCount=10) file_handler.setFormatter(logging.Formatter( &#39;%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]&#39;)) app.logger.addHandler(file_handler) app.logger.setLevel(logging.INFO) ``` #### 2. 健康检查接口 ```python @app.route(&#39;/health&#39;) def health_check(): try: # 简单推理测试 test_input = np.zeros((1,224,224,3)) model.predict(test_input) return &#39;OK&#39;, 200 except Exception as e: return str(e), 500 ``` --- **关键部署路径**: 1. 开发环境验证 → 压力测试(使用Locust/JMeter) 2. 灰度发布(先部署10%流量) 3. 全量上线后持续监控(推荐使用Prometheus + Grafana) 部署完成后建议定期执行模型更新(推荐使用Canary Release模式),并保持API版本兼容性(如/v1/predict、/v2/predict并行运行)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值