
简介一份基于Hadoop的百度云盘系统完整源码与配套文档面向大数据相关专业的在校学生、毕业设计工作者以及希望上手分布式存储的初学者。压缩包共包含2000个文件整体容量77.11MB文件类型以Java后端源码、JSP动态页面、前端网页样式与交互脚本、项目配置文件及依赖库为主前后端层次清晰。所有核心代码均经过运行验证功能可用并附带说明文档可帮助读者梳理Hadoop分布式文件系统与Web应用结合的设计思路理解文件上传下载、元数据管理等关键环节。包内还提供了大量页面展示图片和界面样式资源便于对照效果或进行二次开发改进。目前已有535人学习下载适合作为毕业设计参考案例、课程设计作业或大数据入门的实践项目。1. 基于Hadoop的百度云盘到底是个什么项目先看它解决了什么很多人第一次看到“基于Hadoop的百度云盘”这个标题第一反应是“用Hadoop做一个百度云盘网页版”对也不对。它本质是一个把 HDFSHadoop 分布式文件系统当成后端存储的网盘项目前端用 Bootstrap EasyUI 做管理界面用户能注册、登录、上传、下载、建目录、删文件但底层存数据的不是本地磁盘而是 HDFS 的数据节点。你上传一个文件它会被切块复制到多个节点这正好是大数据课设里最容易被答辩老师追问的分布式存储场景。这类项目适合三类人一是计算机相关专业做毕设或课设的学生想拿 HDFS 实操来证明“我懂大数据”二是刚学完 Hadoop 想找个完整工程练手的 Java 开发者能从 Web 层一路看到分布式存储调用三是想快速搭一套内部文件管理演示系统的工程师——当然生产环境另说。源码里已经整合了登录鉴权、文件操作、目录树大部分功能是跑通的下载后重点不是改代码而是配合文档把环境和参数吃透。下面我从架构讲起再给部署步骤、二次开发思路和踩坑记录最后附一个我常用的 HDFS 数据迁移技巧。2. 核心架构与数据流HDFS 在网盘里扮演什么角色2.1 整体技术栈Java Web EasyUI 前端 HDFS 客户端打开项目源码你能看到ace.min.css、bootstrap.min.css、easyui.css这些前端资源说明界面并不是现在流行的 Vue/React而是基于 EasyUI 这套老牌后台框架。后端几乎可以肯定是 Java WebServlet 或 Spring MVCHadoop 官方提供的 Java API 直接封装成 Service 层。这种组合在课程设计里非常标准EasyUI 负责后台布局和表格渲染Bootstrap 做页面美化HDFS 客户端负责跟 NameNode 和 DataNode 通信。这种选型在今天看起来不是“最潮”的但它有一个非常大的优势链路短。前端发起请求 → Controller 接收参数 → Service 调用FileSystemAPI → HDFS 返回结果。中间没有 Kafka、没有微服务任何一个环节出问题用日志就能快速定位。对毕设而言答辩老师最关心的是“你怎么调用 HDFS 的 API上传文件的副本因子是多少数据块多大”这些恰恰是这个项目最实在的考点。2.2 文件上传下载一条完整的 HDFS 读写链路网盘的核心功能就是文件传输。在基于 HDFS 的云盘里上传逻辑一般是这样// 伪代码摘自项目中常见实现非完整源码 Configuration conf new Configuration(); conf.set(fs.defaultFS, hdfs://localhost:9000); FileSystem fs FileSystem.get(conf); Path remotePath new Path(/user/file/ filename); FSDataOutputStream out fs.create(remotePath, true); byte[] buffer new byte[1024 * 1024]; int len -1; while ((len in.read(buffer)) ! -1) { out.write(buffer, 0, len); } out.close(); fs.close();这段代码里fs.defaultFS指定的是 HDFS 的 NameNode 地址fs.create会拿第三个参数当副本因子默认 3写入流会先写进 DataNode 的本地磁盘再通过 pipeline 复制到其他节点。很多人第一次跑项目看到上传慢以为是代码问题其实是你本地 Hadoop 是伪分布式模式只有一个 DataNode副本因子配成 3 它也存不了三份只会报异常或者默默降级。下载逻辑就反过来FSDataInputStream in fs.open(remotePath); IOUtils.copyBytes(in, response.getOutputStream(), conf);这里有个容易被忽视的坑response是 HTTP 响应对象如果你在构造下载时设置了Content-Disposition文件名必须对中文名做 URL 编码否则前端拿到的文件名是乱码。源码里如果没做编码你下载中文文件名时大概率会遇到这个问题。2.3 元数据怎么设计目录树与文件表的取舍HDFS 本身没有“文件夹”的概念Path只是逻辑路径。所以网盘系统要自己建一张元数据表记录每个用户的目录结构、文件名、大小、上传时间、HDFS 路径。常见的做法有两种把用户和路径直接映射到 HDFS 目录/user/zhangsan/登录后只加载这个前缀下的文件。这种最简单删除目录就是fs.delete递归删。用 MySQL 存元数据HDFS 只存文件块。推荐项目里用这种方式因为后续做用户配额、回收站、分享链接都在 MySQL 里做更省事。我一般会这样设计表字段id、user_id、parent_id、file_name、hdfs_path、file_size、file_type、create_time、is_delete。注意is_delete不是真的去调fs.delete而是把记录标记为删除这样回收站功能好实现。源码里的文档说明如果没提表结构你可以看doc目录下的 SQL 文件里面通常会带建表语句。3. 把项目跑起来环境准备、参数配置与部署顺序3.1 Hadoop 伪分布式环境搭建三个关键配置不管代码写得多好第一步永远是先把 Hadoop 跑起来。推荐用 Hadoop 2.x/3.x 的伪分布式模式内存要求不高一般 8G 内存的笔记本就能带起来。核心配置文件就三个core-site.xmlproperty namefs.defaultFS/name valuehdfs://localhost:9000/value /property property namehadoop.tmp.dir/name value/home/hadoop/tmp/value /propertyhdfs-site.xmlproperty namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name value/home/hadoop/name/value /property property namedfs.datanode.data.dir/name value/home/hadoop/data/value /propertymapred-site.xml或yarn-site.xml按默认配置即可如果只是跑网盘MapReduce 其实用不到但 Hadoop 进程需要 YARN 正常启动才不会报协议版本错误。特别注意hadoop.tmp.dir和dfs.namenode.name.dir不能放在/tmp下否则系统重启清空/tmp后你的 NameNode 格式化数据就没了。这是 Hadoop 新人第一大坑。启动顺序是先hdfs namenode -format初始化只有第一次需要然后start-dfs.sh再用jps确认有NameNode、DataNode、SecondaryNameNode三个进程。如果没有DataNode多半是dfs.datanode.data.dir目录不存在或没有写权限mkdir -p建目录再重启即可。3.2 源码导入与配置项修改别踩端口冲突项目源码一般是 Eclipse/Maven 工程.classpath文件本身就是 Eclipse 格式你可以直接用 Eclipse 导入。如果是 IDEA选 import project from existing sources选 Maven 模型等依赖下载完。需要修改的地方集中在项目里的hadoop.properties或application.xml配置文件hdfs.defaultFshdfs://localhost:9000 hdfs.usernamehadoop hdfs.homeDir/user hdfs.replication1hdfs.username很关键。HDFS 有权限校验如果你用 root 启动 Hadoop而 Web 项目进程是 tomcat在/user下建目录时会被Permission denied挡住。最省事的做法是在hdfs-site.xml里临时加一条property namedfs.permissions.enabled/name valuefalse/value /property这是伪分布式环境下的开发取巧方式生产环境绝对不能这么干。等你跑通了再考虑用Kerberos或ranger做真正权限控制。另外Hadoop 默认占用的端口比较多最常见的冲突是 8088YARN Web UI和你 Tomcat 的 8080 没关系但 50070HDFS Web UI会被某些监控软件占用。改端口在hdfs-site.xml里加dfs.namenode.http-address或者干脆把占用端口的进程停掉。3.3 部署顺序与验收清单给第一次跑项目的人一个顺序参考确认 JDK 版本1.8 最稳Hadoop 3.x 需要 1.8。配置 SSH localhost 免密登录否则 start-dfs.sh 会要求输入密码。格式化 NameNode启动 DFS。建好 HDFS 根目录hdfs dfs -mkdir -p /user。初始化 MySQL 表导入项目里带的 SQL 文件。启动 Tomcat访问登录页。注册一个新用户上传一个文件再下载回来对比 MD5。验收的时候别只看页面显示成功。到 HDFS 里看看实际存储hdfs dfs -ls /user/zhangsan hdfs dfs -du -h /user/zhangsan如果能看到文件且大小一致才说明 Web 层到 HDFS 的链路真的通了。很多项目页面报成功其实只是把文件存到了 Tomcat 临时目录根本没走 HDFS这种假成功比失败更坑。4. 二次开发实战给云盘加上用户配额、分片上传和回收站4.1 用户目录隔离与空间配额源码自带的用户体系一般比较简单登录后所有用户共用/user根目录。我建议改成每个用户一个独立目录并加上配额限制这样更像真实网盘。思路是注册时在 HDFS 上为每个用户创建目录Path userPath new Path(/user/username_ userId); if (!fs.exists(userPath)) { fs.mkdirs(userPath); }配额既可以用 HDFS 原生的配额命令也可以在元数据表里加一个quota字段每次上传时算一下当前用户已用空间SELECT SUM(file_size) FROM t_file WHERE user_id ? AND is_delete 0然后跟配额比对。HDFS 原生配额有个坑hdfs dfs -setQuota只能限制文件数量不能限制空间大小setSpaceQuota可以但是对目录递归生效修改粒度粗。所以我一般推荐在应用层做配额简单直接答辩时也好解释。4.2 分片上传与断点续传稳定性的关键改造HDFS 对超大单文件处理没问题但 Web 上传受限于 Tomcat 的maxPostSize和网络中断风险。网盘项目如果不做分片超过 2GB 的文件基本传不上去。改造方案如下前端用 JavaScript 把文件切片每片 8MB。后端每接收一片就追加写入 HDFS 的同一个文件。记录已上传分片索引下次续传时跳过已存在的分片。HDFS 追加写的核心 API 是FSDataOutputStream的append方法但要注意 HDFS 默认不支持对文件任意位置追加只支持在文件末尾追加。所以分片顺序不能乱必须保证严格按编号写入。代码示意FSDataOutputStream out; if (!fs.exists(filePath)) { out fs.create(filePath); } else { out fs.append(filePath); } out.write(bytes); out.hflush(); // 重要不 flush 缓存后续分片可能未落盘 out.close();参数说明append模式需要在hdfs-site.xml里打开dfs.support.appendHadoop 2.6 默认开启hflush是把客户端缓冲区数据刷到 DataNode但不等所有副本确认适合连续追加如果你要严格保证数据完整可以调out.flush()性能会差一点。这个改造做完上传大文件基本不会中断。断点续传只需要前端把已上传分片序号传给后端后端在写文件前跳过对应的长度偏移——不过 HDFS 的append不支持从中间插入所以我们的做法是“已上传的分片如果没写进同一个文件就重传那片”。效率低一点但逻辑简单可靠。4.3 回收站实现把删除变成软删除真正的百度云盘删除文件后会进回收站30 天内可恢复。HDFS 自身有一个.Trash机制开启后fs.delete会转移到用户目录下.Trash中。但这对网盘业务不够灵活因为要跟用户界面交互。我的做法是删除时只更新t_file表is_delete 1HDFS 文件不动。回收站页列出所有is_delete 1且delete_time 30天的记录。恢复时把is_delete改回 0。清理时批量调用 HDFSfs.delete(new Path(hdfsPath), true)然后删除数据库记录。注意一个坑如果多个文件共享同一个 HDFS 路径比如不同用户上传了同名文件你硬删一个会把另一个也删了。所以建表时就要保证hdfs_path对每条记录唯一或者在路径里加上用户 ID 和随机后缀。5. 避坑指南Hadoop 云盘踩坑最多的五个地方5.1 上传文件后页面报 500日志里是FileAlreadyExistsException现象同一个文件重复上传第二次直接报“文件已存在”。原因HDFS 的fs.create默认不允许覆盖已有文件。项目里写死了fs.create(path, false)。解决改成fs.create(path, true)或者在创建前先fs.delete(path, true)。但要注意覆盖前确认是不是同一个用户、同一个目录避免误删。5.2 启动后jps没有 DataNode只有 NameNode现象格式化能过但 DataNode 进程就是起不来日志提示Initialization failed for Block pool.原因伪分布式模式下多次格式化 NameNode 导致clusterID不匹配。格式化会生成新的 clusterIDDataNode 本地存的 clusterID 还是旧的。解决先删掉dfs.datanode.data.dir下的所有数据和dfs.namenode.name.dir下的数据再重新hdfs namenode -format。血泪经验格式化之前先备份数据。5.3 上传大文件时 Tomcat 直接报MaxUploadSizeExceededException现象文件超过几百 MB前端显示上传失败后端日志是 Tomcat 的 maxPostSize 异常。原因Tomcat 默认限制单个 POST 请求 2MBmaxPostSize分片没做或者配置文件没改。解决如果你做完了分片上传每片控制在 8MB 以内但 Tomcat 默认 2MB 依然不够。需要修改 Tomcat 的server.xml里Connector加maxPostSize0或maxSwallowSize104857600。注意0表示不限制但也意味着可能被恶意请求拖垮建议设一个合理值如 100MB。5.4 下载的文件 MD5 和原文件不一致现象上传下载都能完成但下载文件大小小了或者文件损坏。原因多半是上传时没有用二进制流或者读取 HDFSFSDataInputStream时用了字符流导致数据被转码。解决上传下载全部用IOUtils.copyBytes不要自己写readLine。另外检查代码里有没有对OutputStream做flush。我习惯在写完最后一块后调用out.hflush()然后out.close()确保客户端缓冲全部落盘。5.5 用户删除文件后HDFS 空间没有释放现象删除了大量文件hdfs dfs -du看空间还是没变化。原因只做了数据库软删除没调 HDFS 删除接口。解决确认你的删除逻辑里有fs.delete(path, true)执行并且 DataNode 的垃圾回收dfs.trash.interval默认 0表示不回收。如果你开了 HDFS Trash删除后文件会进.Trash占空间需要手动清空或设置周期。6. 进阶技巧用 distcp 做集群间备份和迁移当你把这个云盘项目真正用起来用户上传的文件会越来越多。伪分布式只有一台机器数据安全性很差。我一般会给项目加一个自动备份机制把线上集群的 HDFS 数据定期同步到另一台备用机器或对象存储。这里要用到 Hadoop 自带的distcp工具。先看最常用的命令hadoop distcp -update -delete hdfs://192.168.1.10:9000/user hdfs://192.168.1.11:9000/user参数说明-update表示只同步源端比目标端新的文件-delete表示删除目标端多出来的文件——这个参数适合做镜像同步但要注意如果你之前误删了源端数据-delete会把目标端也删掉。所以我一般把它拆成两步# 第一步增量同步 hadoop distcp -update hdfs://192.168.1.10:9000/user hdfs://192.168.1.11:9000/user # 第二步验证数据量 hadoop distcp -numListstatusThreads 10 -stats /tmp/distcp_stats第二步不是真正验证数据完整性但可以通过-stats输出同步的文件数、字节数。你要是想验证每个文件的 MD5得自己写脚本hdfs dfs -ls -R /user /tmp/source_list while read line; do src_path$(echo $line | awk {print $NF}) src_md5$(hdfs dfs -cat $src_path | md5sum) tgt_md5$(hdfs dfs -cat ${src_path/192.168.1.10/192.168.1.11} | md5sum) if [ $src_md5 ! $tgt_md5 ]; then echo Mismatch: $src_path fi done /tmp/source_list注意这种方式只适合小数据量大数据量还是靠hadoop distcp自带的校验机制它在拷贝时会对每个文件做 CRC32 校验-update只复制大小或时间戳不同的文件。所以日常同步我推荐直接跑-update每个月做一次全量校验防止源端数据静默损坏。另外还有一个参数值得记住-m控制并发 map 数量。默认每个文件一个 map如果你的文件数量特别多比如几十万个小文件可以加-m 20提高并发但伪分布式只有 2 个核心的话并发太高反而会把节点压垮。我一般取 510。最后说说我的习惯每次修改了元数据表结构或者调整了 HDFS 目录策略我都要先跑一遍hdfs dfsadmin -report看数据节点状态再对网盘里最有代表性的几个文件做上传下载验证。从那以后这个项目再也没出现过“页面正常但文件丢了”的翻车。希望这份笔记能帮你在复现或者改造时少走几步弯路。本文还有配套的精品资源点击获取