文件传到 99% 断了,能不能安全续传?我用飞算 JavaAI 跑了一次上传链路
常见问题Q飞算JavaAI能实现大文件分片上传和断点续传吗A飞算JavaAI在文件上传链路测试中实现了分片上传、断点续传、文件类型校验和安全扫描等完整链路覆盖了UPLOADING到MERGING到SCANNING到AVAILABLE的状态流转。Q文件上传时如何防止类型伪装A飞算JavaAI同时校验文件扩展名和实际内容类型文件头服务端生成存储文件名禁止将客户端原始文件名直接拼入磁盘路径。Q扫描未通过的文件能否被下载A不能。系统要求扫描通过且授权成立时才允许下载扫描失败或超时均返回隔离状态QUARANTINED无法下载。文件传到 99% 断了能不能安全续传我用飞算 JavaAI 跑了一次上传链路文件上传经常被写成一个MultipartFile接口然后就算结束。换成大文件和多人协作场景后分片、秒传、安全扫描、访问权限一个都躲不过。“首次可运行”只算中间节点。分片合并成功而且未扫描文件确实无法下载才停表。这个时间更接近日常开发里的完成时间。测试文件准备了三份一个正常的小图片、一个被拆成若干分片的大文件以及一个把扩展名改成.jpg的非图片文件。文件内容全部是公开或临时生成的测试数据不使用工作资料。一、从一次 99% 的中断上传开始这次记两个时间点服务第一次启动以及扫描通过的素材第一次成功下载。计时从发需求开始到第二个时间点才停。中间分片报错、补安全规则全都算进去。环境说明记录 IDEA、JDK、插件、存储方式和安全扫描服务的实现。缺少这些条件上传耗时没有可比性。3.9.0 与 3.9.9 都使用智能路由从上传会话、分片接收、合并一直做到扫描状态。安全扫描接入隔离测试环境中的可替换实现接口、超时和失败回调都按真实外部服务处理扫描失败或服务超时绝不能被误判为“文件安全”。本次测试环境如下。环境项本次配置操作系统与硬件macOS 26.6.1IntelliJ IDEA2026.2.1飞算 JavaAI3.9.0 与 3.9.9两轮均使用智能路由模式后端Java 17 Spring Boot 4.5Maven 3.9.14前端Vue 3 ViteNode.js 26.3.0构建与缓存Maven 3.9.14数据库MySQL 8.4 LTS3.9.0 与 3.9.9 都从同一份空工程开始使用相同文件、分片大小和存储目录。安全扫描端返回相同的成功、失败和超时响应。任一轮如果改了文件大小或跳过扫描用时都不能直接放进同一张表。素材的状态线需要覆盖上传和扫描两个阶段UPLOADING → MERGING → SCANNING → AVAILABLE ├─ 分片错误 → UPLOAD_FAILED └─ 扫描失败 → QUARANTINED图 1测试环境二、先把“上传完成”拆成五道门后端要保存上传会话、分片、扫描结果和授权记录前端只负责发起上传、续传、查看扫描状态和下载。上传进度、素材状态和下载权限都要以接口结果为准。2.1 我提交的 Prompt开发一套独立的素材上传与治理前后端项目。后端使用 Java Spring Boot 提供 REST API、文件处理和状态管理前端使用 Vue Vite上传、续传、扫描状态和下载都必须调用后端接口不能用前端进度条模拟完成。 先梳理上传会话、分片记录、素材元数据、扫描任务和授权记录的职责给出状态流转、接口清单和生成顺序后再实现。 需要包含创建上传会话、分片上传、查询进度、断点续传、合并、类型校验、扫描结果回调、授权管理和下载。 状态至少覆盖 UPLOADING → MERGING → SCANNING → AVAILABLE并处理 UPLOAD_FAILED 和 QUARANTINED。扫描未通过、扫描超时或结果未返回时文件都不能下载。 分片可乱序上传和重试合并前必须校验分片数量、序号与摘要。重复上传同一分片不能重复计数也不能静默覆盖为不同内容。 文件类型同时校验扩展名和实际内容类型或文件头服务端生成存储文件名禁止把客户端原始文件名直接拼进磁盘路径。下载接口必须校验所有者、授权对象和有效期。 前端提供上传队列、分片进度、素材列表、扫描状态、授权和下载入口。补充分片缺失、类型伪装、扫描失败、未授权下载与断点续传的关键测试并给出项目启动和联调说明。另外补两条口径每个分片带序号和摘要合并前检查数量与摘要文件类型既看扩展名也看内容类型或文件头。加摘要不是为了增加无关复杂度而是为了知道重传或合并有没有把文件弄坏。需求拆解时重点检查上传会话、分片记录、素材元数据、扫描任务和授权记录有没有被区分。文件字节存在磁盘和素材已经可以被业务使用是两件事。只有扫描通过并且授权成立下载接口才应该返回内容。接口顺序也要清楚创建会话、上传分片、查询进度、触发合并、接收扫描结果、授权、下载。上传分片可以乱序和重试合并动作则必须检查数量、序号与摘要是否完整。2.2 从需求到源码的五步Prompt 提交后我先看它怎么理解“文件已传上去”和“文件可以下载”的差别接着检查接口是否把上传、合并、扫描、授权拆成独立动作表结构则重点看上传会话、分片记录、素材元数据和扫描任务是否各自留痕。生成计划排在代码前面能看出它有没有把扫描状态和下载校验留到最后补救。图 2测试 Prompt图 3理解需求图 4接口设计图 5表结构图 6生成计划图 7生成源码三、续传不是补几个分片“素材上传与治理中心”前端负责创建上传会话、显示分片进度、查看安全扫描结果、配置访问授权并发起下载。一个文件从进入上传队列到进入素材库始终使用同一条任务记录页面状态由后端流程真实推进。图 8续传验证停表前要满足三项工程能够编译启动UPLOADING → SCANNING → AVAILABLE正常跑通分片缺失、类型伪装、扫描失败和未授权下载都有明确处理。普通上传接口能用还不算完成这道题。测试时选定同一份文件从页面创建上传任务按分片上传并触发合并等待扫描结果后再下载。完成后同时核对最终文件摘要、数据库元数据和授权记录三处一致才算上传成功。页面操作会故意中断一次上传到一半后刷新再根据上传会话查询已经存在的分片只补缺失部分。全部上传完成后先尝试下载应该因扫描未完成被拒绝收到安全结果以后再次下载才返回文件内容。这样能把进度续传、状态控制和下载权限连成一条真实链路。操作完成条件按乱序上传全部分片按序合并最终摘要与原文件一致缺少一个分片就请求合并拒绝合并并返回缺失序号重复上传同一分片不重复计数内容不被悄悄覆盖伪装成图片的其他文件类型校验失败不进入扫描完成状态扫描中的文件请求下载即使知道文件 ID 也不能下载四、扫描前文件还不能算素材我主要看异步状态有没有被处理明白。文件上传完不代表已经可用扫描失败更不能悄悄进素材库。状态一变下载权限也得跟着变。文件内容和数据库状态之间也可能不一致。合并文件写成功、元数据更新失败时要能清理临时文件或重新执行元数据已经显示可用而文件不存在则下载接口必须返回可诊断错误。这次实战可以先使用本地文件存储但失败路径不能完全不提。下载时查资源所有者、授权对象和有效期。只给列表接口做权限没用别人拿到文件 ID 直接调下载接口照样可能绕过去。URL 也不能一直公开设计里至少得交代怎么过期。路径处理和摘要验证是这次的检查重点客户端传来的原始文件名不能直接拼接到磁盘路径核心源码对比分片合流完整性与安全下载门禁两版在分片合并和下载边界上的处理不同飞算 JavaAI 3.9.0直接拼接分片// 3.9.0 生成实现简单流拷贝拼接缺少哈希指纹比对与下载门禁 public String mergeChunks(String uploadId, String filename) throws Exception { File chunkDir new File(/tmp/uploads/ uploadId); File[] chunks chunkDir.listFiles(); // 缺陷1仅按文件系统默认顺序读写分片顺序错乱时合并文件损坏 File mergedFile new File(/data/files/ filename); try (FileOutputStream fos new FileOutputStream(mergedFile)) { for (File chunk : chunks) { Files.copy(chunk.toPath(), fos); } } // 缺陷2直接返回可公开下载的静态路径未完成病毒扫描SCANNING的文件可被外部直接读取 return http://localhost:8080/files/ filename; }说明3.9.0 首轮代码没有排序和摘要校验。分片顺序错乱时合并结果无法确认下载也没有根据扫描状态拦截。飞算 JavaAI 3.9.9校验后进入扫描// 3.9.9 生成实现严格分片索引排序 流式计算 SHA-256 状态机安全下载拦截 Transactional(rollbackFor Exception.class) public AssetMergeResponseVO mergeChunksAndVerify(AssetMergeDTO dto, UserContext user) { // 1. 获取会话并严格验证分片总数与路径穿越防御 UploadSession session uploadSessionMapper.selectByUploadId(dto.getUploadId()); if (session null || !session.getUserId().equals(user.getUserId())) { throw new BusinessException(ErrorCode.UNAUTHORIZED_SESSION, 非法上传会话或无权操作); } Path finalPath storageRoot.resolve(session.getAssetId() .dat).normalize(); if (!finalPath.startsWith(storageRoot)) { throw new SecurityException(非法路径穿越检测拦截); } // 2. 按 chunkIndex 严格升序合并同时流式计算全局 SHA-256 指纹 try (OutputStream fos Files.newOutputStream(finalPath)) { MessageDigest digest MessageDigest.getInstance(SHA-256); for (int i 0; i session.getTotalChunks(); i) { Path chunkPath tempChunkDir.resolve(session.getUploadId() _ i); if (!Files.exists(chunkPath)) { throw new BusinessException(ErrorCode.CHUNK_MISSING, 缺失分片: i); } byte[] bytes Files.readAllBytes(chunkPath); digest.update(bytes); fos.write(bytes); } String calculatedHash HexFormat.of().formatHex(digest.digest()); // 3. 核对客户端传入的预期哈希确保文件完整无损 if (dto.getExpectedHash() ! null !dto.getExpectedHash().equalsIgnoreCase(calculatedHash)) { Files.deleteIfExists(finalPath); throw new BusinessException(ErrorCode.HASH_MISMATCH, 文件 SHA-256 校验失败分片已损坏); } // 4. 更新素材元数据状态流转为待扫描SCANNING下载接口强制拦截未过审文件 Asset asset Asset.builder() .assetId(session.getAssetId()) .name(session.getOriginalFilename()) .storagePath(finalPath.toString()) .sha256Hash(calculatedHash) .status(AssetStatusEnum.SCANNING.getCode()) // 强制进入扫描队列禁止未过审直链分发 .build(); assetMapper.updateById(asset); return AssetMergeResponseVO.builder() .assetId(asset.getAssetId()) .hash(calculatedHash) .status(asset.getStatus()) .build(); } catch (Exception e) { throw new BusinessException(ErrorCode.MERGE_FAILED, 合并分片失败: e.getMessage()); } }说明3.9.9 首轮代码加入了路径、缺失分片和 SHA-256 校验并把合并后的文件置为SCANNING。下载接口是否完全封住还要结合授权和临时 Token 用例验证。五、耗时要沿着上传链路记录阶段耗时 / 结果需求输入与追问5 分 40 秒代码生成8 分 30 秒首次编译通过Maven 编译 0 错误修复到成功启动3 分 50 秒配置临时分片存储目录与生命周期清理跑通核心流程16 分 20 秒分片上传、SHA-256 合流与授权下载总耗时34 分 20 秒对照版本总耗时3.9.0 为 82 分 10 秒3.9.9 为 34 分 20 秒人工修改文件数 / 代码量2 个文件 / 约 38 行代码分片越界防御与下载状态门禁最终摘要是否一致一致合流前后 SHA-256 哈希值完全匹配首次安全检查发现的问题分片索引越界未严格校验、未完成扫描的素材可通过原始路径旁路读取构建通过后还要过文件完整性和访问权限两关这两部分会单独记录。验收项首次结果修改后结果正常流程通过分片并行上传、合流、哈希指纹计算、状态推进通过业务流转完整重复请求通过相同 chunkIndex 重复投递幂等覆盖且不影响总进度通过状态幂等非法状态或边界输入需加固扫描处理中状态下缺少严格下载阻断通过补齐状态门禁与临时 Token 鉴权文件大小、分片大小、分片数量都写进结果。5 MB 和 5 GB 当然不能直接比。这次主要测流程对不对不拿本地磁盘速度冒充系统吞吐。图 10结果对比六、最后看它能不能挡住错误下载结果里同时列“第一次能跑”和“达到验收线”两个时间。前一个只反映首轮生成后一个才接近交付成本。再看 3.9.0 与 3.9.9 在这两个时间点上的差异。摘要一致、扫描、下载授权三道关的时间都算进来。对比项飞算 JavaAI 3.9.0飞算 JavaAI 3.9.9差值首轮代码生成19 分 20 秒8 分 30 秒快 10 分 50 秒-56.0%首次可启动37 分 10 秒14 分 20 秒节省 22 分 50 秒-61.4%扫描通过且素材可下载45 分 00 秒20 分 00 秒节省 25 分 00 秒-55.6%总耗时82 分 10 秒34 分 20 秒节省 47 分 50 秒-58.3%本次使用单机存储和隔离扫描端不覆盖对象存储分片协议、CDN 和超大文件跨节点合并。它可以验证上传流程、安全状态与授权边界不能拿本机磁盘结果推导生产吞吐。本次评价优点在这组固定文件和用例下3.9.9 首次编译为 0 错误从需求提交到扫描通过且可下载用时由 45 分降到 20 分总耗时由 82 分 10 秒降到 34 分 20 秒。不足安全扫描与下载授权边界需要手动加固首轮生成未默认对扫描中SCANNING和病毒隔离QUARANTINE状态的素材文件在下载端做硬性拦截缺少临时签名防盗链机制。建议智能路由可以用于快速搭建上传工作流上线前需保留摘要一致性、断点恢复、扫描失败和越权下载这四类验收。#飞算JavaAI #AI编程 #Java #Java代码生成 #Java开发 #SpringBoot

相关新闻

最新新闻

日新闻

周新闻

月新闻