当前位置: 首页 > news >正文

FLASK与JAVA的多文件互传(多文件互传亲测)

java:

flask:

# # 安装 Windows 兼容版本
# pip install python-magic-bin
# pip install flask

java代码:

package HttpFlask;import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;/*** 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 uploadMultiple(String url, Map<String, File> files,Map<String, String> textParams) throws IOException {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpPost httpPost = new HttpPost(url);MultipartEntityBuilder builder = MultipartEntityBuilder.create();// 添加多个文件if (files != null) {for (Map.Entry<String, File> entry : files.entrySet()) {String fieldName = entry.getKey(); // 表单字段名File file = entry.getValue();FileBody fileBody = new FileBody(file,ContentType.DEFAULT_BINARY, file.getName());builder.addPart(fieldName, fileBody);}}// 添加文本参数if (textParams != null) {textParams.forEach((key, value) ->builder.addTextBody(key, value));}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);}}}//上传多个文件public static UploadResult uploadFilesWithMap(String url,Map<String,File> files)throws IOException {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpPost uploadFile = new HttpPost(url);MultipartEntityBuilder builder = MultipartEntityBuilder.create();// 添加文件,使用不同的字段名for (Map.Entry<String, File> entry : files.entrySet()) {builder.addPart(entry.getKey(), new FileBody(entry.getValue()));}// 添加其他表单参数builder.addPart("category", new StringBody("文档", ContentType.TEXT_PLAIN));builder.addPart("compress", new StringBody("true", ContentType.TEXT_PLAIN));HttpEntity multipart = builder.build();uploadFile.setEntity(multipart);try (CloseableHttpResponse response = httpClient.execute(uploadFile)) {int statusCode = response.getStatusLine().getStatusCode();String responseBody = EntityUtils.toString(response.getEntity());return new UploadResult(statusCode, responseBody,statusCode >= 200 && statusCode < 300);}}}/*** 创建默认请求配置*/private static RequestConfig createDefaultRequestConfig() {return RequestConfig.custom().setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectionRequestTimeout(15000).build();}/*** 创建自定义超时配置*/public static RequestConfig createCustomConfig(int connectTimeout, int socketTimeout) {return RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).build();}/*** 上传结果封装类*/public static class UploadResult {private final int statusCode;private final String responseBody;private final boolean success;public UploadResult(int statusCode, String responseBody, boolean success) {this.statusCode = statusCode;this.responseBody = responseBody;this.success = success;}public int getStatusCode() { return statusCode; }public String getResponseBody() { return responseBody; }public boolean isSuccess() { return success; }@Overridepublic String toString() {return String.format("UploadResult{statusCode=%d, success=%s, response='%s'}",statusCode, success,responseBody.length() > 100 ? responseBody.substring(0, 100) + "..." : responseBody);}}
}

java测试代码:

package HttpFlask;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class FileHttpFlask {public static void main(String[] args) {try {// 示例4: 多文件上传,flask字典接受Map<String, File> files = new HashMap<>();files.put("file1", new File("E:\\testWorkPlace\\testrun\\src\\testHtt\\down.txt"));files.put("file2", new File("E:\\testWorkPlace\\testrun\\src\\testHtt\\upload.txt"));Map<String, String> parameH = new HashMap<>();parameH.put("category", "huitao");parameH.put("compress", "true");String urlMore="http://127.0.0.1:5000/api/upload-multiple_dict";FileUploader4514.UploadResult multiResult =FileUploader4514.uploadMultiple(urlMore, files, parameH);System.out.println("多文件上传结果dict: " + multiResult);// 示例4: 多文件上传,flask列表接受// 使用不同的字段名(Map的键)Map<String, File> filess = new HashMap<>();String urlList="http://127.0.0.1:5000/api/upload-multiple-filelist";filess.put("file1", new File("E:\\testWorkPlace\\testrun\\src\\testHtt\\down.txt"));filess.put("file2", new File("E:\\testWorkPlace\\testrun\\src\\testHtt\\upload.txt"));filess.put("file3", new File("E:\\testWorkPlace\\testrun\\src\\testHtt\\list.txt"));FileUploader4514.UploadResult multilist = FileUploader4514.uploadFilesWithMap(urlList,filess);System.out.println("多文件上传结果list: " + multilist);} 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,  # 16MBALLOWED_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:"""文件上传工具类"""@staticmethoddef allowed_file(filename):"""检查文件扩展名"""return '.' in filename and \filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']@staticmethoddef 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}"@staticmethoddef get_file_info(file_path):"""获取文件详细信息"""stat = os.stat(file_path)file_type = "unknown"try:# 使用python-magic检测文件类型import magicfile_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-multiple_dict', methods=['POST'])
def api_upload_multiple_dict():try:# 将文件转换为字典格式files_dict = request.files.to_dict()if not files_dict:return jsonify({'success': False, 'error': '没有文件部分'}), 400saved_files = []for field_name, file_storage in files_dict.items():if file_storage.filename:  # 确保不是空文件filename = secure_filename(file_storage.filename)file_path = os.path.join('uploads', filename)file_storage.save(file_path)saved_files.append({'field_name': field_name,'original_name': file_storage.filename,'saved_name': filename,'size': os.path.getsize(file_path),'content_type': file_storage.content_type})# 处理其他参数category = request.form.get('category', '')compress = request.form.get('compress') == 'true'return jsonify({'success': True,'message': f'成功上传 {len(saved_files)} 个文件','files': saved_files,'category': category,'compress': compress})except Exception as e:return jsonify({'success': False, 'error': str(e)}), 500#多文件上传
@app.route('/api/upload-multiple-filelist', methods=['POST'])
def api_upload_multiple_fileslist():"""接收Java Map<String, File> 格式的多文件上传"""try:# 调试信息:查看请求中的所有文件字段print("请求中的文件字段:", list(request.files.keys()))print("表单参数:", dict(request.form))# 获取所有上传的文件uploaded_files = request.filesif not uploaded_files:return jsonify({'success': False,'error': '没有接收到任何文件'}), 400saved_files = []# 遍历所有文件字段(对应Java Map的键)for field_name, file_storage in uploaded_files.items():# 检查文件是否有效(有文件名且不为空)if file_storage and file_storage.filename and file_storage.filename.strip():# 安全处理文件名original_filename = file_storage.filenamesafe_filename = secure_filename(original_filename)# 如果安全处理后文件名为空,使用原始文件名(去除路径)if not safe_filename:safe_filename = original_filename.split('\\')[-1]  # 处理Windows路径safe_filename = safe_filename.split('/')[-1]  # 处理Linux路径# 构建保存路径file_path = os.path.join(app.config['UPLOAD_FOLDER'], safe_filename)try:# 保存文件file_storage.save(file_path)# 获取文件大小file_size = os.path.getsize(file_path)saved_files.append({'field_name': field_name,  # Java Map中的键名:file1, file2, document'original_name': original_filename,'saved_name': safe_filename,'file_path': file_path,'size': file_size,'content_type': file_storage.content_type or 'application/octet-stream'})print(f"成功保存文件: {field_name} -> {safe_filename} ({file_size} bytes)")except Exception as file_error:print(f"保存文件 {field_name} 时出错: {str(file_error)}")continueelse:print(f"跳过无效文件字段: {field_name}")# 检查是否有文件成功保存if not saved_files:return jsonify({'success': False,'error': '没有有效的文件被上传'}), 400# 获取表单参数(对应Java中的StringBody参数)category = request.form.get('category', 'default')compress = request.form.get('compress', 'false').lower() == 'true'print(f"接收到的参数 - category: {category}, compress: {compress}")# 返回成功响应return jsonify({'success': True,'message': f'成功上传 {len(saved_files)} 个文件','uploaded_files': saved_files,'parameters': {'category': category,'compress': compress},'total_size': sum(f['size'] for f in saved_files)}), 200except Exception as e:print(f"上传处理异常: {str(e)}")return jsonify({'success': False,'error': f'服务器处理错误: {str(e)}'}), 500# 错误处理
@app.errorhandler(413)
def too_large(e):return jsonify({'success': False, 'error': '文件太大'}), 413@app.errorhandler(500)
def internal_error(e):return jsonify({'success': False, 'error': '服务器内部错误'}), 500if __name__ == '__main__':app.run(debug=True, host='0.0.0.0', port=5000)

测试结果:

http://www.dtcms.com/a/427055.html

相关文章:

  • 蓝牙音箱的技术演进:从便捷到高保真的音频革命
  • 打破信息孤岛,构建统一视界:视频融合平台EasyCVR在智慧校园建设中的核心作用
  • 计算机应用技术网站开发基础知识网店推广平台
  • 快速完美解决在CefSharp.WinForms.ChromiumWebBrowser浏览器中无法播放视频的问题
  • 【高并发服务器:前置知识】一、项目介绍 模块划分
  • 数据结构入门 (五):约束即是力量 —— 深入理解栈
  • 如何搭建网站的结构丰台专业网站建设公司
  • Web渗透之一句话木马
  • 网站建设如何选择服务器百度做公司网站多少钱
  • Vscode+CMake编译时出现中文乱码
  • 38、spark读取hudi报错:java.io.NotSerializableException: org.apache.hadoop.fs.Path
  • 三年级上册语文快乐读书吧读书笔记+知识点(格林童话、安徒生童话、稻草人)+三年级语文快乐读书吧笔记汇总+完整电子版可下载打印
  • 迅为Hi3516CV610开发板强劲内核-海思Hi3516CV610核心板
  • 网站开发可以当程序员wordpress 怎么迁移
  • babelfish for postgresql 分析--babelfishpg_tds--doing
  • 手机网站排行榜焦作专业网站建设费用
  • 小程序开发:开启定制化custom-tab-bar但不生效问题,以及使用NutUI-React Taro的安装和使用
  • 避坑指南:关于文件夹加密软件(以“文件夹加密超级大师”为例)卸载前的正确操作流程
  • 用矩阵实现元素绕不定点旋转
  • Web UI自动化测试学习系列5--基础知识1--常用元素定位1
  • 大模型-扩散模型(Diffusion Model)原理讲解(2)
  • 一文讲解反射、注解
  • 学习日报 20250930|优惠券事务处理模块
  • 【Nest.js】模块之间依赖关系,以及导出导入链的完整性
  • MyBatis —— 多表操作和注解开发
  • 自动化脚本的自动化执行实践
  • 有颜二维码 1.0.5| 告别单调,一键生成有颜色的二维码
  • 信创浪潮下的国产组态软件——紫金桥RealSCADA
  • 做网站新闻移动动态网络规划设计师资料及视频教程
  • 机器学习之三大学习范式:监督学习、无监督学习、强化学习