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

测试结果:

相关推荐
万邦科技Lafite20 小时前
京东按图搜索京东商品(拍立淘) API (.jd.item_search_img)快速抓取数据
开发语言·前端·数据库·python·电商开放平台·京东开放平台
丁浩66620 小时前
Python机器学习---6.集成学习与随机森林
python·随机森林·机器学习
默 语21 小时前
MySQL中的数据去重,该用DISTINCT还是GROUP BY?
java·数据库·mysql·distinct·group by·1024程序员节·数据去重
charlie11451419121 小时前
现代 Python 学习笔记:Statements & Syntax
笔记·python·学习·教程·基础·现代python·python3.13
oDeviloo1 天前
新版IntelliJ IDEA个性化设置兼容老版习惯
java·ide·intellij-idea
一只小透明啊啊啊啊1 天前
Java Web 开发的核心组件:Servlet, JSP,Filter,Listener
java·前端·servlet
spencer_tseng1 天前
Eclipse Uninstall Software
java·ide·eclipse
嗯、.1 天前
使用 iText 9 为 PDF 添加文字水印的完整实战
java·pdf·itext
麦麦大数据1 天前
F036 vue+flask中医热性药知识图谱可视化系统vue+flask+echarts+mysql
vue.js·python·mysql·flask·可视化·中医中药
怪兽20141 天前
缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题
java·缓存·面试