FLASK与JAVA的文件互传并带参数以及流上传(单文件互传亲测)

JAVA:

flask:

JAVA代码:FileUploader4514.java

复制代码
/**
 * HttpClient 4.5.14 文件上传工具类
 */
public class FileUploader4514 {

    // 默认配置
    private static final int DEFAULT_CONNECT_TIMEOUT = 30000; // 30秒
    private static final int DEFAULT_SOCKET_TIMEOUT = 60000;  // 60秒

    /**
     * 上传文件到指定URL
     */
    public static UploadResult upload(String url, File file,
                                      Map<String, String> textParams) throws IOException {
        return upload(url, file, file.getName(), textParams, null);
    }

    /**
     * 上传文件(带自定义配置)
     */
    public static UploadResult upload(String url, File file, String fileName,
                                      Map<String, String> textParams,
                                      RequestConfig requestConfig) throws IOException {

        if (requestConfig == null) {
            requestConfig = createDefaultRequestConfig();
        }

        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .build()) {

            HttpPost httpPost = new HttpPost(url);

            // 构建多部分实体
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            builder.setCharset(StandardCharsets.UTF_8);

            // 添加文件
            FileBody fileBody = new FileBody(file,
                    ContentType.DEFAULT_BINARY,
                    fileName);
            builder.addPart("file", fileBody);

            // 添加文本参数
            if (textParams != null) {
                for (Map.Entry<String, String> entry : textParams.entrySet()) {
                    StringBody paramBody = new StringBody(entry.getValue(),
                            ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8));
                    builder.addPart(entry.getKey(), paramBody);
                }
            }

            HttpEntity multipartEntity = builder.build();
            httpPost.setEntity(multipartEntity);

            // 添加请求头(可选)
            httpPost.setHeader("User-Agent", "FileUploader/1.0");

            // 执行上传
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                int statusCode = response.getStatusLine().getStatusCode();
                String responseBody = EntityUtils.toString(response.getEntity());
                EntityUtils.consume(response.getEntity());

                return new UploadResult(statusCode, responseBody,
                        statusCode >= 200 && statusCode < 300);
            }
        }
    }
/**
     * 通过输入流上传文件
     */
    public static UploadResult uploadStream(String url, InputStream inputStream,
                                            String fileName, long fileSize,
                                            Map<String, String> textParams) throws IOException {

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();

            // 使用InputStreamBody处理输入流
            InputStreamBody inputStreamBody = new InputStreamBody(inputStream,
                    ContentType.DEFAULT_BINARY, fileName);
            builder.addPart("file", inputStreamBody);

            // 添加文件大小信息(如果已知)
            if (fileSize > 0) {
                builder.addTextBody("fileSize", String.valueOf(fileSize));
            }

            // 添加文本参数
            if (textParams != null) {
                textParams.forEach((key, value) ->
                        builder.addTextBody(key, value,
                                ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8)));
            }

            httpPost.setEntity(builder.build());

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                int statusCode = response.getStatusLine().getStatusCode();
                String responseBody = EntityUtils.toString(response.getEntity());

                return new UploadResult(statusCode, responseBody,
                        statusCode >= 200 && statusCode < 300);
            }
        }
    }
}

JAVA的测试代码:

复制代码
public static void main(String[] args) {

        try {

            // 示例2: 使用工具类上传(带参数)
            Map<String, String> params = new HashMap<>();
            params.put("description", "测试文件上传");
            params.put("tags", "12345");

            String urlSingle = "http://127.0.0.1:5000/api/upload";
            File file = new File("E:\\testWorkPlace\\testrun\\src\\HttpFlask\\upload.txt");
            //上传带参数的文件
            FileUploader4514.UploadResult uploadResult =
                    FileUploader4514.upload(urlSingle, file, params);
            System.out.println("工具类上传结果: " + uploadResult);

// 示例3: 使用输入流上传
            try (FileInputStream fis = new FileInputStream(file)) {
                FileUploader4514.UploadResult streamResult =
                        FileUploader4514.uploadStream(urlSingle, fis,   "E:\\testWorkPlace\\testrun\\src\\testHtt\\upload.txt",
                                file.length(), params);
                System.out.println("流上传结果: " + streamResult);
            }
} catch (IOException e) {
            e.printStackTrace();
        }

}
}

flask:

复制代码
from flask import Flask, request, jsonify, render_template_string, send_file
import os
import uuid
from werkzeug.utils import secure_filename
from datetime import datetime
import magic  # 用于更准确的文件类型检测
from datetime import datetime
import time
# # 安装 Windows 兼容版本
# pip install python-magic-bin
app = Flask(__name__)

# 配置文件上传
app.config.update(
    UPLOAD_FOLDER='uploads',
    MAX_CONTENT_LENGTH=16 * 1024 * 1024,  # 16MB
    ALLOWED_EXTENSIONS={'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx', 'zip'},
    SECRET_KEY='your-secret-key-here'
)

# 用于存储上传统计信息
upload_stats = {
    'total_files': 0,
    'total_size': 0,
    'last_upload': None
}
# 创建上传目录
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)


class FileUploader:
    """文件上传工具类"""

    @staticmethod
    def allowed_file(filename):
        """检查文件扩展名"""
        return '.' in filename and \
               filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

    @staticmethod
    def generate_unique_filename(original_filename):
        """生成唯一文件名"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
        unique_id = str(uuid.uuid4())[:8]
        safe_name = secure_filename(original_filename)
        return f"{timestamp}_{unique_id}_{safe_name}"

    @staticmethod
    def get_file_info(file_path):
        """获取文件详细信息"""
        stat = os.stat(file_path)
        file_type = "unknown"

        try:
            # 使用python-magic检测文件类型
            import magic
            file_type = magic.from_file(file_path, mime=True)
        except:
            # 备用方案:使用文件扩展名
            ext = os.path.splitext(file_path)[1].lower()
            file_type = f"application/{ext[1:]}" if ext else "unknown"

        return {
            'size': stat.st_size,
            'created_time': datetime.fromtimestamp(stat.st_ctime).isoformat(),
            'modified_time': datetime.fromtimestamp(stat.st_mtime).isoformat(),
            'type': file_type
        }




@app.route('/api/upload', methods=['POST'])
def api_upload_file():
    """API: 单文件上传"""
    try:
        if 'file' not in request.files:
            return jsonify({'success': False, 'error': '没有文件部分'}), 400

        file = request.files['file']
        description = request.form.get('description', '')
        tags = request.form.get('tags', '')

        print("description:",description)
        print("tags:",tags)

        if file.filename == '':
            return jsonify({'success': False, 'error': '没有选择文件'}), 400

        if not FileUploader.allowed_file(file.filename):
            return jsonify({'success': False, 'error': '不允许的文件类型'}), 400

        # 生成唯一文件名
        unique_filename = FileUploader.generate_unique_filename(file.filename)
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)

        # 保存文件
        file.save(file_path)

        # 获取文件信息
        file_info = FileUploader.get_file_info(file_path)

        response_data = {
            'success': True,
            'message': '文件上传成功',
            'file': {
                'id': unique_filename,
                'original_name': file.filename,
                'saved_name': unique_filename,
                'description': description,
                'tags': [tag.strip() for tag in tags.split(',')] if tags else [],
                'upload_time': datetime.now().isoformat(),
                **file_info
            }
        }

        return jsonify(response_data), 200

    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 500

测试结果:

相关推荐
豆沙沙包?5 分钟前
2025年--Lc293-784. 字母大小写全排列(回溯)--java版
java·开发语言
q***996312 分钟前
【MyBatisPlus】MyBatisPlus介绍与使用
java
豆奶特浓616 分钟前
Java面试生死局:谢飞机遭遇在线教育场景,从JVM、Spring Security到AI Agent,他能飞吗?
java·jvm·微服务·ai·面试·spring security·分布式事务
秋邱26 分钟前
智启未来:AGI 教育融合 × 跨平台联盟 × 个性化空间,重构教育 AI 新范式开篇:一场 “教育 ×AI” 的范式革命
人工智能·python·重构·推荐算法·agi
爱吃泡芙的小白白31 分钟前
vscode、anaconda、git、python配置安装(自用)
ide·git·vscode·python·anaconda·学习记录
谷隐凡二31 分钟前
Kubernetes主从架构简单解析:基于Python的模拟实现
python·架构·kubernetes
老歌老听老掉牙38 分钟前
Matplotlib Pyplot 数据可视化完全指南
python·信息可视化·matplotlib
Sunhen_Qiletian41 分钟前
《Python开发之语言基础》第六集:操作文件
前端·数据库·python
Python编程学习圈1 小时前
Python真的要一统天下了?
python
前端世界1 小时前
float 还是 double?用储罐体积计算带你看懂 C 语言浮点数的真实世界坑
java·c语言·开发语言