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

测试结果:

相关推荐
雨夜的星光2 小时前
PyCharm 核心快捷键大全 (Windows版)
ide·python·pycharm
Stream_Silver2 小时前
LangChain入门实践3:PromptTemplate提示词模板详解
java·python·学习·langchain·language model
小树懒(-_-)3 小时前
SEO:Java项
java·开发语言
许泽宇的技术分享3 小时前
Ansible核心架构深度剖析:从源码看IT自动化的“简单“哲学
python·ansible·自动化运维·devops·it基础设施
TeleostNaCl3 小时前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea
小蕾Java3 小时前
IntelliJ IDEA 2025:最新使用图文教程!
java·ide·intellij-idea
风遥~3 小时前
快速了解并使用Matplotlib库
人工智能·python·数据分析·matplotlib
聪明的笨猪猪3 小时前
Java “线程池(1)”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
Miraitowa_cheems3 小时前
LeetCode算法日记 - Day 63: 图像渲染、岛屿数量
java·数据结构·算法·leetcode·决策树·贪心算法·深度优先