diff --git a/.gitignore b/.gitignore
index 8d58268..4b86c52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,32 +1,31 @@
-*.class
-
-# Package Files #
-*.jar
-*.war
-*.ear
-
-# Build Artifacts
-
-.gradle/
-build/
+HELP.md
target/
-bin/
-dependency-reduced-pom.xml
-
-# Eclipse Project Files
+.mvn
+### STS ###
+.apt_generated
.classpath
+.factorypath
.project
-.settings/
-
-# IntelliJ IDEA Files
+.settings
+.springBeans
+.sts4-cache
+### IntelliJ IDEA ###
+.idea
+*.iws
*.iml
*.ipr
-*.iws
-*.idea
-README.html
-gradlew
-gradlew.bat
-gradle
\ No newline at end of file
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
\ No newline at end of file
diff --git a/README.md b/README.md
index 8334354..60c28f2 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,4 @@
# Breakpoint-http
-
-
-
## 目录
* [背景介绍](#背景介绍)
* [项目介绍](#项目介绍)
@@ -17,99 +14,81 @@
* [秒传功能](#秒传功能)
* [断点续传](#断点续传)
* [总结](#总结)
+* [后续](#后续)
+
+
## 背景介绍
+*Breakpoint-http*,是不是觉得这个名字有点low,break point断点。这是一个大文件上传的一种实现。因为本来很久没写过前端了,本来想自己好好写一番js,可惜因为种种原因而作罢了。该项目是基于一款百度开源的前端上传控件:**WebUploader**。
+*Breakpoint-http*,当初想实现这一块web大文件上传,是因为有一天同时询问我这方面的知识,我发现好像在实战中没写过这类的代码啊。既然知道了自己不足那肯定要狠狠补一下。所以才有了这个项目。这个项目是gradle+Spring Boot可能有部分人还没接触过这两个东西,这里就不进行讲解了,毕竟这不是重点,把gradle当成maven吧,虽然它还有更出色的功能。Spring Boot用来简化Spring应用的初始搭建以及开发过程,一个约定大于规范的框架。
- *Breakpoint-http*,是不是觉得这个名字有点low,break point断点。这是一个大文件上传的一种实现。因为本来很久没写过前端了,本来想自己好好写一番js,可惜
-因为种种原因而作罢了。该项目是基于一款百度开源的前端上传控件:WebUploader(百度开源的东西文档一如既往的差,哈哈。或者是我理解能力差)。
- *Breakpoint-http*,当初想实现这一块web大文件上传,是因为有一天同时询问我这方面的知识,我发现好像在实战中没写过这类的代码啊。既然知道了自己不足那
-肯定要狠狠补一下。所以才有了这个项目。
-
- 对了这个项目是gradle+Spring Boot可能有部分人还没接触过这两个东西,这里就不进行讲解了,毕竟这不是重点,把gradle当成maven吧,虽然它还有更出色的功能。
-Spring Boot用来简化Spring应用的初始搭建以及开发过程,一个约定大于规范的框架。
## 项目介绍
-
- *Breakpoint-http* 是一个基于大文件上传,并参考网盘上传文件,而基于web的大文件上传实现项目。web中上传大文件没有桌面软件那么容易,还好现在是身处于
-一个html5的时代。我们web端上传文件常用的做法就是用表单上传了,一旦上传的文件大小较大,一旦带宽跟不上,那用户只能在哪里一直等着,不能做刷新页面的操作,
-并且一旦产生网络波动,那么用户所做的一切就白费了。
- *Breakpoint-http*就是为了保证在web端上传大文件能达到基本的可靠性的一种方案,方法多种,可能的方案会更出色,欢迎讨论。要让大文件上传能达到可用性,我们需要做到怎么样的程度呢?
+*Breakpoint-http* 是一个基于大文件上传,并参考网盘上传文件,而基于web的大文件上传实现项目。web中上传大文件没有桌面软件那么容易,还好现在是身处于一个html5的时代。我们web端上传文件常用的做法就是用表单上传了,一旦上传的文件大小较大,一旦带宽跟不上,那用户只能在哪里一直等着,不能做刷新页面的操作,并且一旦产生网络波动,那么用户所做的一切就白费了。
+*Breakpoint-http*就是为了保证在web端上传大文件能达到基本的可靠性的一种方案,方法多种,可能的方案会更出色,欢迎讨论。要让大文件上传能达到可用性,我们需要做到怎么样的程度呢?
* **断点续传** 最主要的功能之一,在断网或者在暂停的情况下,能够在上传断点中继续上传。
* **分块上传** 也是断点续传的基础之一,把大文件通过前端分块,然后后台在组在一起。
-* **文件妙传** 这个相信大家在网盘中见过不少了,就是服务中已经有人上传过得文件,其他人再上传这个文件就秒上传到服务中去。
-* **其他功能** 把下面这些功能归类到其他,是因为它们基本都是通过WebUploader()来实现的,很简单。
+* **文件秒传** 这个相信大家在网盘中见过不少了,就是服务中已经有人上传过得文件,其他人再上传这个文件就秒上传到服务中去。
+* **其他功能** 把下面这些功能归类到其他,是因为它们基本都是通过[WebUploader]()来实现的,很简单。
* *多线程上传* 多个线程上传不同的块文件。
* *文件进度显示* 显示文件的上传完成情况。
- * UI等等。
-
+ * *UI* 等等
+
+
+
## 使用说明
### 获取代码
-* GitHub:
-* OSChina项目主页:
-持续更新。
-
+* GitHub:
### 需要知识点
-- 基于spring boot开发的。
+- 基于spring boot开发的,springboot1.x和springboot2.x有较大的差别,需要注意,推荐springboot2.x,其是当前使用的主流框架。
- WebUploader,WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。
-- redis,key-value存储系统,在这里我把redis用作存储文件路径来使用。
-- Gradle,Gradle是一个基于JVM的构建工具。这里我用Gradle顶替了Maven。嗯,多学点东西。
-
+- redis, key-value存储系统,在这里我把redis用作存储文件路径来使用。
+- Gradle, Gradle是一个基于JVM的构建工具。这里我用Gradle顶替了Maven。
### 启动项目
-
-1. main方法直接运行:
-(1)找到App启动类(win.pangniu.learn包下)
-(2)执行main方法。
+1. main方法直接运行:
+(1)找到BreakPointHttpApplication启动类(com.zgy.learn包下)
+(2)执行main方法。
(3)然后用浏览器访问:
-
-2. tomcat运行:
-(1)执行命令gradle war。
-(2)在out目录下找到bphttp.war包。
-(3)拷贝到tomcat,然后运行tomcat。
-(4)然后用浏览器访问:
-
### 项目示范
-
1. 上传完后的页面
-
-2. 妙传功能演示页面
-
+
+2. 秒传功能演示页面
+
+3. 修改过后的样式
+
详情自己运行就知道。
+
+
## 核心讲解
### 核心原理
- 该项目核心就是文件分块上传。前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题。
- * 如何分片;
- * 如何合成一个文件;
- * 中断了从哪个分片开始。
- 如何分,利用强大的js库,来减轻我们的工作,市场上已经能有关于大文件分块的轮子,虽然程序员的天性曾迫使我重新造轮子。但是因为时间的关系还有工作的关系,我只能罢休了。最后我选择了百度的WebUploader来实现前端所需。
- 如何合,在合之前,我们还得先解决一个问题,我们如何区分分块所属那个文件的。刚开始的时候,我是采用了前端生成了唯一uuid来做文件的标志,在每个分片请求上带上。不过后来在做秒传的时候我放弃了,采用了Md5来维护分块和文件关系。
- 在服务端合并文件,和记录分块的问题,在这方面其实行业已经给了很好的解决方案了。参考迅雷,你会发现,每次下载中的时候,都会有两个文件,一个文件主体,另外一个就是文件临时文件,临时文件存储着每个分块对应字节位的状态。
-这些都是需要前后端密切联系才能做好,前端需要根据固定大小对文件进行分片,并且请求中要带上分片序号和大小。前端发送请求顺利到达后台后,服务器只需要按照请求数据中给的分片序号和每片分块大小(分片大小是固定且一样的)算出开始位置,与读取到的文件片段数据,写入文件即可。
+该项目核心就是文件分块上传。前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题。
+* 如何分片;
+* 如何合成一个文件;
+* 中断了从哪个分片开始。
+**如何分**,利用强大的js库,来减轻我们的工作,市场上已经能有关于大文件分块的轮子,虽然程序员的天性曾迫使我重新造轮子。但是因为时间的关系还有工作的关系,我只能罢休了。最后我选择了百度的WebUploader来实现前端所需。
+**如何合**,在合之前,我们还得先解决一个问题,我们如何区分分块所属那个文件的。刚开始的时候,我是采用了前端生成了唯一uuid来做文件的标志,在每个分片请求上带上。不过后来在做秒传的时候我放弃了,*采用了Md5来维护分块和文件关系*。
+在服务端合并文件,和记录分块的问题,在这方面其实行业已经给了很好的解决方案了。参考迅雷,你会发现,每次下载中的时候,都会有两个文件,一个文件主体,另外一个就是文件临时文件,临时文件存储着每个分块对应字节位的状态。这些都是需要前后端密切联系才能做好,前端需要根据固定大小对文件进行分片,并且请求中要带上分片序号和大小。前端发送请求顺利到达后台后,服务器只需要按照请求数据中给的分片序号和每片分块大小(分片大小是固定且一样的)算出开始位置,与读取到的文件片段数据,写入文件即可。
+
## 功能分析
-
### 分块上传
- 分块上传可以说是我们整个项目的基础,像断点续传、暂停这些都是需要用到分块。
-分块这块相对来说比较简单。前端是采用了webuploader,分块等基础功能已经封装起来,使用方便。
-借助webUpload提供给我们的文件API,前端就显得异常简单。
-
-
-
-```
- // 实例化wu
+分块上传可以说是我们整个项目的基础,像断点续传、暂停这些都是需要用到分块。分块这块相对来说比较简单。前端是采用了webuploader,分块等基础功能已经封装起来,使用方便。借助webuploader提供给我们的文件API,前端就显得异常简单。
+```javascript
+ // 实例化
var uploader = WebUploader.create({
pick: {
id: '#picker',
@@ -136,10 +115,10 @@ Spring Boot用来简化Spring应用的初始搭建以及开发过程,一个约
fileSingleSizeLimit: 1024 * 1024 * 1024 // 50 M
});
```
- 分则必合。把大文件分片了,但是分片了就没有原本文件功能,所以我们要把分片合成为原本的文件。我们只需要把分片按原本位置写入到文件中去。因为前面原理那一部我们已经讲到了,我们知道分块大小和分块序号,我就可以知道该分块在文件中的起始位置。所以这里使用RandomAccessFile是明智的,RandomAccessFile能在文件里面前后移动。但是在andomAccessFile的绝大多数功能,已经被JDK1.4的NIO的“内存映射文件(memory-mapped files)”取代了。我在该项目中分别写了使用RandomAccessFile与MappedByteBuffer来合成文件。分别对应的方法是uploadFileRandomAccessFile和uploadFileByMappedByteBuffer。两个方法代码如下。
+**分则必合**。把大文件分片了,但是分片了就没有原本文件功能,所以我们要把分片合成为原本的文件。我们只需要把分片按原本位置写入到文件中去。因为前面原理那一部我们已经讲到了,我们知道分块大小和分块序号,我就可以知道该分块在文件中的起始位置。所以这里使用RandomAccessFile是明智的,RandomAccessFile能在文件里面前后移动。但是在RandomAccessFile的绝大多数功能,已经被JDK1.4的NIO的“内存映射文件(memory-mapped files)”取代了。我在该项目中分别写了使用RandomAccessFile与MappedByteBuffer来合成文件。分别对应的方法是uploadFileRandomAccessFile和uploadFileByMappedByteBuffer。两个方法代码如下。
-```
- public void uploadFileRandomAccessFile(MultipartFileParam param) throws IOException {
+```java
+ public void uploadFileRandomAccessFile(MultipartFileParam param) throws IOException {
String fileName = param.getName();
String tempDirPath = finalDirPath + param.getMd5();
String tempFileName = fileName + "_tmp";
@@ -151,9 +130,9 @@ Spring Boot用来简化Spring应用的初始搭建以及开发过程,一个约
RandomAccessFile accessTmpFile = new RandomAccessFile(tmpFile, "rw");
long offset = CHUNK_SIZE * param.getChunk();
- //定位到该分片的偏移量
+ // 定位到该分片的偏移量
accessTmpFile.seek(offset);
- //写入该分片数据
+ // 写入该分片数据
accessTmpFile.write(param.getFile().getBytes());
// 释放
accessTmpFile.close();
@@ -164,51 +143,48 @@ Spring Boot用来简化Spring应用的初始搭建以及开发过程,一个约
System.out.println("upload complete !!" + flag + " name=" + fileName);
}
}
-
+
public void uploadFileByMappedByteBuffer(MultipartFileParam param) throws IOException {
- String fileName = param.getName();
- String uploadDirPath = finalDirPath + param.getMd5();
- String tempFileName = fileName + "_tmp";
- File tmpDir = new File(uploadDirPath);
- File tmpFile = new File(uploadDirPath, tempFileName);
- if (!tmpDir.exists()) {
- tmpDir.mkdirs();
- }
-
- RandomAccessFile tempRaf = new RandomAccessFile(tmpFile, "rw");
- FileChannel fileChannel = tempRaf.getChannel();
-
- //写入该分片数据
- long offset = CHUNK_SIZE * param.getChunk();
- byte[] fileData = param.getFile().getBytes();
- MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
- mappedByteBuffer.put(fileData);
- // 释放
- FileMD5Util.freedMappedByteBuffer(mappedByteBuffer);
- fileChannel.close();
-
- boolean isOk = checkAndSetUploadProgress(param, uploadDirPath);
- if (isOk) {
- boolean flag = renameFile(tmpFile, fileName);
- System.out.println("upload complete !!" + flag + " name=" + fileName);
- }
+ String fileName = param.getName();
+ String uploadDirPath = finalDirPath + param.getMd5();
+ String tempFileName = fileName + "_tmp";
+ File tmpDir = new File(uploadDirPath);
+ File tmpFile = new File(uploadDirPath, tempFileName);
+ if (!tmpDir.exists()) {
+ tmpDir.mkdirs();
}
+
+ RandomAccessFile tempRaf = new RandomAccessFile(tmpFile, "rw");
+ FileChannel fileChannel = tempRaf.getChannel();
+
+ // 写入该分片数据
+ long offset = CHUNK_SIZE * param.getChunk();
+ byte[] fileData = param.getFile().getBytes();
+ MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
+ mappedByteBuffer.put(fileData);
+ // 释放
+ FileMD5Util.freedMappedByteBuffer(mappedByteBuffer);
+ fileChannel.close();
+
+ boolean isOk = checkAndSetUploadProgress(param, uploadDirPath);
+ if (isOk) {
+ boolean flag = renameFile(tmpFile, fileName);
+ System.out.println("upload complete !!" + flag + " name=" + fileName);
+ }
+ }
```
-
### 秒传功能
-
- 秒传功能,相信大家都体现过了,网盘上传的时候,发现上传的文件秒传了。其实原理稍微有研究过的同学应该知道,其实就是检验文件MD5,记录下上传到系统的文件的MD5,在一个文件上传前先获取文件内容MD5值或者部分取值MD5,然后在匹配系统上的数据。
- *Breakpoint-http*实现秒传原理,客户端选择文件之后,点击上传的时候触发获取文件MD5值,获取MD5后调用系统一个接口(/index/checkFileMd5),查询该MD5是否已经存在(我在该项目中用redis来存储数据,用文件MD5值来作key,value是文件存储的地址。)接口返回检查状态,然后再进行下一步的操作。相信大家看代码就能明白了。
- 嗯,前端的MD5取值也是用了webuploader自带的功能,这还是个不错的工具。
-
+**秒传功能**,相信大家都体验过了,网盘上传的时候,发现上传的文件秒传了。其实原理稍微有研究过的同学应该知道,其实就是检验文件MD5,记录下上传到系统的文件的MD5,在一个文件上传前先获取文件内容MD5值或者部分取值MD5,然后在匹配系统上的数据。
+*Breakpoint-http*实现秒传原理,客户端选择文件之后,点击上传的时候触发获取文件MD5值,获取MD5后调用系统一个接口(`/index/checkFileMd5`),查询该MD5是否已经存在(我在该项目中用redis来存储数据,用文件MD5值来作key,value是文件存储的地址。)接口返回检查状态,然后再进行下一步的操作。相信大家看代码就能明白了。前端的MD5取值也是用了webuploader自带的功能,这还是个不错的工具。
### 断点续传
- 断点续传,就是在文件上传的过程中发生了中断,人为因素(暂停)或者不可抗力(断网或者网络差)导致了文件上传到一半失败了。然后在环境恢复的时候,重新上传该文件,而不至于是从新开始上传的。
- 前面也已经讲过,断点续传的功能是基于分块上传来实现的,把一个大文件分成很多个小块,服务端能够把每个上传成功的分块都落地下来,客户端在上传文件开始时调用接口快速验证,条件选择跳过某个分块。
- 实现原理,就是在每个文件上传前,就获取到文件MD5取值,在上传文件前调用接口(/index/checkFileMd5,没错也是秒传的检验接口)如果获取的文件状态是未完成,则返回所有的还没上传的分块的编号,然后前端进行条件筛算出哪些没上传的分块,然后进行上传。
-```
-/**
+**断点续传**,就是在文件上传的过程中发生了中断,人为因素(暂停)或者不可抗力(断网或者网络差)导致了文件上传到一半失败了。然后在环境恢复的时候,重新上传该文件,而不至于是从新开始上传的。
+;前面也已经讲过,断点续传的功能是基于分块上传来实现的,把一个大文件分成很多个小块,服务端能够把每个上传成功的分块都落地下来,客户端在上传文件开始时调用接口快速验证,条件选择跳过某个分块。
+实现原理,就是在每个文件上传前,就获取到文件MD5取值,在上传文件前调用接口(/index/checkFileMd5,没错也是秒传的检验接口)如果获取的文件状态是未完成,则返回所有的还没上传的分块的编号,然后前端进行条件筛算出哪些没上传的分块,然后进行上传。
+
+```java
+ /**
* 秒传判断,断点判断
*
* @return
@@ -237,15 +213,32 @@ Spring Boot用来简化Spring应用的初始搭建以及开发过程,一个约
return new ResultVo<>(ResultStatus.ING_HAVE, missChunkList);
}
}
-```
+```
+
+
## 总结
- 身为一个具有拖延症的程序猿,写个文档及其不容易,这方面还是优待加强,写代码时间都还没写这个文档长,并且写了那么久还那么烂的文档。实在抱歉,望谅解。
- 项目的Bug和改进点,可在评论去留言或者在GitHub或者OSChina上以issue的方式直接提交给我,谢谢大家。
+身为一个具有拖延症的程序猿,写个文档及其不容易,这方面还是有待加强,写代码时间都还没写这个文档长,并且写了那么久还那么烂的文档。实在抱歉,望谅解。
+项目的Bug和改进点,可在评论去留言或者在GitHub或者OSChina上以issue的方式直接提交给我,谢谢大家。
+
+
+
+
+## 后续
+由于本项目使用的是Gradle+redis的方案,对于目前的一般项目而言,Gradle使用的还比较少,redis也是一种方式,传统的数据库,在使用之中还是有比较广泛的
+使用基础,如果当项目之中使用了数据库,或者不太想引入redis的时候,我们就可以采用mybatis存取相关的数据,在`store-mysql`的分支之中,我继续使用了
+Gradle的管理方式,但是就目前而言,其对于mapper.xml文件的打包,还有些许问题,而使用maven+mybatis(mybatis-plus)的方式在我的github
+[springboot2.x-integration](https://github.com/prayjourney/springboot2.x-integration)的master分支之中集成了功能,并且可以正常
+运行,如果访问github网速过慢,可以访问gitee的[springboot2.x-integration](https://gitee.com/zuiguangyin123/springboot2.x-integration)
+的master分支,同时如果有问题或者发现bug, 可以提issue给我,欢迎fork或者star。
+
+
+
+## 更新记录
+当前默认分支是springboot2.x, 修改项目为springboot2+redis+maven的方式。
+
-##参考文献
-[1]http://fex.baidu.com/webuploader/
-[2]http://www.zuidaima.com/blog/2819949848316928.htm
-[3]https://my.oschina.net/feichexia/blog/212318
\ No newline at end of file
+## 参考文献
+1. http://fex.baidu.com/webuploader/, 2. http://www.zuidaima.com/blog/2819949848316928.htm, 3. https://my.oschina.net/feichexia/blog/212318
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index 1059e49..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,47 +0,0 @@
-group 'win.pangniu.learn'
-version '1.0-SNAPSHOT'
-
-apply plugin: 'java'
-apply plugin: 'war'
-apply plugin: 'maven'
-apply plugin: 'spring-boot'
-
-sourceCompatibility = 1.8
-
-buildscript {
- repositories {
- mavenLocal()
- mavenCentral()
- jcenter()
- }
- dependencies {
- classpath(
- "org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE"
- )
- }
-}
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- compile(
- 'org.springframework.boot:spring-boot-starter-web',
- 'org.springframework.boot:spring-boot-starter-data-redis'
- )
- // https://mvnrepository.com/artifact/commons-io/commons-io
- compile group: 'commons-io', name: 'commons-io', version: '2.5'
- // https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
- compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.2'
- // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
- compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.5'
- //providedCompile("org.springframework.boot:spring-boot-starter-tomcat")
- testCompile group: 'junit', name: 'junit', version: '4.12'
- testCompile('org.springframework.boot:spring-boot-starter-test')
-}
-
-// war
-war {
- archiveName 'bphttp.war'
-}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a76aacd
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,104 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.7.RELEASE
+
+
+ com.zgy.learn
+ Breakpoint-http
+ 0.0.1-SNAPSHOT
+ Breakpoint-http
+ Demo project for Spring Boot
+
+
+ 1.8
+ UTF-8
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ commons-io
+ commons-io
+ 2.5
+
+
+ org.apache.commons
+ commons-lang3
+ 3.5
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.3.2
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
deleted file mode 100644
index 9f4f3e8..0000000
--- a/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-rootProject.name = 'breakpoint-http'
-
diff --git a/src/main/java/com/zgy/learn/BreakPointHttpApplication.java b/src/main/java/com/zgy/learn/BreakPointHttpApplication.java
new file mode 100644
index 0000000..ef26bfb
--- /dev/null
+++ b/src/main/java/com/zgy/learn/BreakPointHttpApplication.java
@@ -0,0 +1,13 @@
+package com.zgy.learn;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class BreakPointHttpApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(BreakPointHttpApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/win/pangniu/learn/controller/IndexController.java b/src/main/java/com/zgy/learn/controller/IndexController.java
similarity index 79%
rename from src/main/java/win/pangniu/learn/controller/IndexController.java
rename to src/main/java/com/zgy/learn/controller/IndexController.java
index 595b8c2..684f752 100644
--- a/src/main/java/win/pangniu/learn/controller/IndexController.java
+++ b/src/main/java/com/zgy/learn/controller/IndexController.java
@@ -1,5 +1,8 @@
-package win.pangniu.learn.controller;
+package com.zgy.learn.controller;
+import com.zgy.learn.param.MultipartFileParam;
+import com.zgy.learn.service.StorageService;
+import com.zgy.learn.utils.Constants;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
@@ -11,11 +14,8 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
-import win.pangniu.learn.param.MultipartFileParam;
-import win.pangniu.learn.service.StorageService;
-import win.pangniu.learn.utils.Constants;
-import win.pangniu.learn.vo.ResultStatus;
-import win.pangniu.learn.vo.ResultVo;
+import com.zgy.learn.vo.ResultStatus;
+import com.zgy.learn.vo.ResultVo;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
@@ -23,11 +23,6 @@
import java.util.LinkedList;
import java.util.List;
-/**
- * 默认控制层
- * Created by wenwen on 2017/4/11.
- * version 1.0
- */
@Controller
@RequestMapping(value = "/index")
public class IndexController {
@@ -41,13 +36,16 @@ public class IndexController {
private StorageService storageService;
/**
- * 秒传判断,断点判断
+ * 秒传判断, 断点判断
*
+ * @param md5
* @return
+ * @throws IOException
*/
@RequestMapping(value = "checkFileMd5", method = RequestMethod.POST)
@ResponseBody
public Object checkFileMd5(String md5) throws IOException {
+ // 从redis之中获取MD5信息
Object processingObj = stringRedisTemplate.opsForHash().get(Constants.FILE_UPLOAD_STATUS, md5);
if (processingObj == null) {
return new ResultVo(ResultStatus.NO_HAVE);
@@ -83,20 +81,18 @@ public Object checkFileMd5(String md5) throws IOException {
public ResponseEntity fileUpload(MultipartFileParam param, HttpServletRequest request) {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
- logger.info("上传文件start。");
+ logger.info("上传文件start!");
try {
// 方法1
- //storageService.uploadFileRandomAccessFile(param);
- // 方法2 这个更快点
+ // storageService.uploadFileRandomAccessFile(param);
storageService.uploadFileByMappedByteBuffer(param);
} catch (IOException e) {
e.printStackTrace();
- logger.error("文件上传失败。{}", param.toString());
+ logger.error("文件上传失败, {}", param.toString());
}
- logger.info("上传文件end。");
+ logger.info("上传文件end!");
}
- return ResponseEntity.ok().body("上传成功。");
+ return ResponseEntity.ok().body("上传成功!");
}
-
}
diff --git a/src/main/java/com/zgy/learn/param/MultipartFileParam.java b/src/main/java/com/zgy/learn/param/MultipartFileParam.java
new file mode 100644
index 0000000..76a68e9
--- /dev/null
+++ b/src/main/java/com/zgy/learn/param/MultipartFileParam.java
@@ -0,0 +1,38 @@
+package com.zgy.learn.param;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 分片上传包装
+ */
+@Getter
+@Setter
+@ToString
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class MultipartFileParam {
+ // 用户id
+ private String uid;
+ // 任务ID
+ private String id;
+ // 总分片数量
+ private int chunks;
+ // 当前为第几块分片
+ private int chunk;
+ // 当前分片大小
+ private long size = 0L;
+ // 文件名
+ private String name;
+ // 分片对象
+ private MultipartFile file;
+ // MD5值
+ private String md5;
+
+}
diff --git a/src/main/java/win/pangniu/learn/service/StorageService.java b/src/main/java/com/zgy/learn/service/StorageService.java
similarity index 84%
rename from src/main/java/win/pangniu/learn/service/StorageService.java
rename to src/main/java/com/zgy/learn/service/StorageService.java
index e6cd87d..05d44ab 100644
--- a/src/main/java/win/pangniu/learn/service/StorageService.java
+++ b/src/main/java/com/zgy/learn/service/StorageService.java
@@ -1,12 +1,11 @@
-package win.pangniu.learn.service;
+package com.zgy.learn.service;
-import win.pangniu.learn.param.MultipartFileParam;
+import com.zgy.learn.param.MultipartFileParam;
import java.io.IOException;
/**
* 存储操作的service
- * Created by 超文 on 2017/5/2.
*/
public interface StorageService {
diff --git a/src/main/java/win/pangniu/learn/service/impl/StorageServiceImpl.java b/src/main/java/com/zgy/learn/service/impl/StorageServiceImpl.java
similarity index 80%
rename from src/main/java/win/pangniu/learn/service/impl/StorageServiceImpl.java
rename to src/main/java/com/zgy/learn/service/impl/StorageServiceImpl.java
index 97b167d..a540850 100644
--- a/src/main/java/win/pangniu/learn/service/impl/StorageServiceImpl.java
+++ b/src/main/java/com/zgy/learn/service/impl/StorageServiceImpl.java
@@ -1,17 +1,16 @@
-package win.pangniu.learn.service.impl;
+package com.zgy.learn.service.impl;
+import com.zgy.learn.param.MultipartFileParam;
+import com.zgy.learn.service.StorageService;
+import com.zgy.learn.utils.Constants;
+import com.zgy.learn.utils.FileMD5Util;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
-import win.pangniu.learn.param.MultipartFileParam;
-import win.pangniu.learn.service.StorageService;
-import win.pangniu.learn.utils.Constants;
-import win.pangniu.learn.utils.FileMD5Util;
import java.io.File;
import java.io.IOException;
@@ -24,19 +23,18 @@
import java.nio.file.Paths;
/**
- * Created by 超文 on 2017/5/2.
+ * 存储操作的service, 具体实现可以由redis, mysql, mongodb等来实现
*/
+@Slf4j
@Service
public class StorageServiceImpl implements StorageService {
-
- private final Logger logger = LoggerFactory.getLogger(StorageServiceImpl.class);
// 保存文件的根目录
- private Path rootPaht;
+ private Path rootPath;
@Autowired
private StringRedisTemplate stringRedisTemplate;
- //这个必须与前端设定的值一致
+ // 这个必须与前端设定的值一致
@Value("${breakpoint.upload.chunkSize}")
private long CHUNK_SIZE;
@@ -45,26 +43,26 @@ public class StorageServiceImpl implements StorageService {
@Autowired
public StorageServiceImpl(@Value("${breakpoint.upload.dir}") String location) {
- this.rootPaht = Paths.get(location);
+ this.rootPath = Paths.get(location);
}
@Override
public void deleteAll() {
- logger.info("开发初始化清理数据,start");
- FileSystemUtils.deleteRecursively(rootPaht.toFile());
+ log.info("开发初始化清理数据, start");
+ FileSystemUtils.deleteRecursively(rootPath.toFile());
stringRedisTemplate.delete(Constants.FILE_UPLOAD_STATUS);
stringRedisTemplate.delete(Constants.FILE_MD5_KEY);
- logger.info("开发初始化清理数据,end");
+ log.info("开发初始化清理数据, end");
}
@Override
public void init() {
try {
- Files.createDirectory(rootPaht);
+ Files.createDirectory(rootPath);
} catch (FileAlreadyExistsException e) {
- logger.error("文件夹已经存在了,不用再创建。");
+ log.error("文件夹已经存在了, 不用再创建!");
} catch (IOException e) {
- logger.error("初始化root文件夹失败。", e);
+ log.error("初始化root文件夹失败. ", e);
}
}
@@ -81,9 +79,9 @@ public void uploadFileRandomAccessFile(MultipartFileParam param) throws IOExcept
RandomAccessFile accessTmpFile = new RandomAccessFile(tmpFile, "rw");
long offset = CHUNK_SIZE * param.getChunk();
- //定位到该分片的偏移量
+ // 定位到该分片的偏移量
accessTmpFile.seek(offset);
- //写入该分片数据
+ // 写入该分片数据
accessTmpFile.write(param.getFile().getBytes());
// 释放
accessTmpFile.close();
@@ -109,7 +107,7 @@ public void uploadFileByMappedByteBuffer(MultipartFileParam param) throws IOExce
RandomAccessFile tempRaf = new RandomAccessFile(tmpFile, "rw");
FileChannel fileChannel = tempRaf.getChannel();
- //写入该分片数据
+ // 写入该分片数据
long offset = CHUNK_SIZE * param.getChunk();
byte[] fileData = param.getFile().getBytes();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
@@ -137,17 +135,17 @@ private boolean checkAndSetUploadProgress(MultipartFileParam param, String uploa
String fileName = param.getName();
File confFile = new File(uploadDirPath, fileName + ".conf");
RandomAccessFile accessConfFile = new RandomAccessFile(confFile, "rw");
- //把该分段标记为 true 表示完成
+ // 把该分段标记为 true 表示完成
System.out.println("set part " + param.getChunk() + " complete");
accessConfFile.setLength(param.getChunks());
accessConfFile.seek(param.getChunk());
accessConfFile.write(Byte.MAX_VALUE);
- //completeList 检查是否全部完成,如果数组里是否全部都是(全部分片都成功上传)
+ // completeList 检查是否全部完成,如果数组里是否全部都是(全部分片都成功上传)
byte[] completeList = FileUtils.readFileToByteArray(confFile);
byte isComplete = Byte.MAX_VALUE;
for (int i = 0; i < completeList.length && isComplete == Byte.MAX_VALUE; i++) {
- //与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUE
+ // 与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUE
isComplete = (byte) (isComplete & completeList[i]);
System.out.println("check part " + i + " complete?:" + completeList[i]);
}
@@ -176,14 +174,14 @@ private boolean checkAndSetUploadProgress(MultipartFileParam param, String uploa
* @return
*/
public boolean renameFile(File toBeRenamed, String toFileNewName) {
- //检查要重命名的文件是否存在,是否是文件
+ // 检查要重命名的文件是否存在,是否是文件
if (!toBeRenamed.exists() || toBeRenamed.isDirectory()) {
- logger.info("File does not exist: " + toBeRenamed.getName());
+ log.info("File does not exist: " + toBeRenamed.getName());
return false;
}
String p = toBeRenamed.getParent();
File newFile = new File(p + File.separatorChar + toFileNewName);
- //修改文件名
+ // 修改文件名
return toBeRenamed.renameTo(newFile);
}
diff --git a/src/main/java/com/zgy/learn/utils/Constants.java b/src/main/java/com/zgy/learn/utils/Constants.java
new file mode 100644
index 0000000..b259894
--- /dev/null
+++ b/src/main/java/com/zgy/learn/utils/Constants.java
@@ -0,0 +1,17 @@
+package com.zgy.learn.utils;
+
+/**
+ * 常量表
+ */
+public interface Constants {
+ /**
+ * 保存文件所在路径的key,eg.FILE_MD5:1243jkalsjflkwaejklgjawe
+ */
+ String FILE_MD5_KEY = "FILE_MD5:";
+
+ /**
+ * 保存上传文件的状态
+ */
+ String FILE_UPLOAD_STATUS = "FILE_UPLOAD_STATUS";
+
+}
diff --git a/src/main/java/win/pangniu/learn/utils/FileMD5Util.java b/src/main/java/com/zgy/learn/utils/FileMD5Util.java
similarity index 96%
rename from src/main/java/win/pangniu/learn/utils/FileMD5Util.java
rename to src/main/java/com/zgy/learn/utils/FileMD5Util.java
index 949b943..fba59b2 100644
--- a/src/main/java/win/pangniu/learn/utils/FileMD5Util.java
+++ b/src/main/java/com/zgy/learn/utils/FileMD5Util.java
@@ -1,7 +1,8 @@
-package win.pangniu.learn.utils;
+package com.zgy.learn.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
@@ -16,10 +17,9 @@
import java.security.PrivilegedAction;
/**
- * 文件md5值
- * Created by 超文 on 2016/10/10.
- * version 1.0
+ * MD5检测工具
*/
+@Component
public class FileMD5Util {
private final static Logger logger = LoggerFactory.getLogger(FileMD5Util.class);
diff --git a/src/main/java/win/pangniu/learn/vo/ResultStatus.java b/src/main/java/com/zgy/learn/vo/ResultStatus.java
similarity index 89%
rename from src/main/java/win/pangniu/learn/vo/ResultStatus.java
rename to src/main/java/com/zgy/learn/vo/ResultStatus.java
index cc30aed..a100f31 100644
--- a/src/main/java/win/pangniu/learn/vo/ResultStatus.java
+++ b/src/main/java/com/zgy/learn/vo/ResultStatus.java
@@ -1,11 +1,9 @@
-package win.pangniu.learn.vo;
+package com.zgy.learn.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 结果类型枚举
- * Created by 超文 on 2017/5/2.
- * version 1.0
*/
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ResultStatus {
diff --git a/src/main/java/com/zgy/learn/vo/ResultVo.java b/src/main/java/com/zgy/learn/vo/ResultVo.java
new file mode 100644
index 0000000..cc05e8e
--- /dev/null
+++ b/src/main/java/com/zgy/learn/vo/ResultVo.java
@@ -0,0 +1,36 @@
+package com.zgy.learn.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+/**
+ * 返回结果包装对象
+ */
+@Setter
+@Getter
+@ToString
+@Accessors(chain = true)
+public class ResultVo {
+
+ private ResultStatus status;
+
+ private String msg;
+
+ private T data;
+
+ public ResultVo(ResultStatus status) {
+ this(status, status.getReasonPhrase(), null);
+ }
+
+ public ResultVo(ResultStatus status, T data) {
+ this(status, status.getReasonPhrase(), data);
+ }
+
+ public ResultVo(ResultStatus status, String msg, T data) {
+ this.status = status;
+ this.msg = msg;
+ this.data = data;
+ }
+}
diff --git a/src/main/java/win/pangniu/learn/App.java b/src/main/java/win/pangniu/learn/App.java
deleted file mode 100644
index 7dbbf59..0000000
--- a/src/main/java/win/pangniu/learn/App.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package win.pangniu.learn;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
-
-/**
- * 启动类
- * Created by wenwen on 2017/4/11.
- * version 1.0
- */
-@SpringBootApplication
-public class App extends SpringBootServletInitializer {
-
- public static void main(String[] args) {
- SpringApplication.run(App.class, args);
- }
-
-}
diff --git a/src/main/java/win/pangniu/learn/param/MultipartFileParam.java b/src/main/java/win/pangniu/learn/param/MultipartFileParam.java
deleted file mode 100644
index e682b29..0000000
--- a/src/main/java/win/pangniu/learn/param/MultipartFileParam.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package win.pangniu.learn.param;
-
-
-import org.springframework.web.multipart.MultipartFile;
-
-/**
- * Created by wenwen on 2017/4/16.
- * version 1.0
- */
-public class MultipartFileParam {
-
- // 用户id
- private String uid;
- //任务ID
- private String id;
- //总分片数量
- private int chunks;
- //当前为第几块分片
- private int chunk;
- //当前分片大小
- private long size = 0L;
- //文件名
- private String name;
- //分片对象
- private MultipartFile file;
- // MD5
- private String md5;
-
- public String getUid() {
- return uid;
- }
-
- public void setUid(String uid) {
- this.uid = uid;
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public int getChunks() {
- return chunks;
- }
-
- public void setChunks(int chunks) {
- this.chunks = chunks;
- }
-
- public int getChunk() {
- return chunk;
- }
-
- public void setChunk(int chunk) {
- this.chunk = chunk;
- }
-
- public long getSize() {
- return size;
- }
-
- public void setSize(long size) {
- this.size = size;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public MultipartFile getFile() {
- return file;
- }
-
- public void setFile(MultipartFile file) {
- this.file = file;
- }
-
- public String getMd5() {
- return md5;
- }
-
- public void setMd5(String md5) {
- this.md5 = md5;
- }
-
- @Override
- public String toString() {
- return "MultipartFileParam{" +
- "uid='" + uid + '\'' +
- ", id='" + id + '\'' +
- ", chunks=" + chunks +
- ", chunk=" + chunk +
- ", size=" + size +
- ", name='" + name + '\'' +
- ", file=" + file +
- ", md5='" + md5 + '\'' +
- '}';
- }
-}
diff --git a/src/main/java/win/pangniu/learn/utils/Constants.java b/src/main/java/win/pangniu/learn/utils/Constants.java
deleted file mode 100644
index 72db398..0000000
--- a/src/main/java/win/pangniu/learn/utils/Constants.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package win.pangniu.learn.utils;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 常量表
- * Created by 超文 on 2017/05/02.
- * version 1.0
- */
-public interface Constants {
- /**
- * 异常信息统一头信息
- * 非常遗憾的通知您,程序发生了异常
- */
- public static final String Exception_Head = "boom。炸了。";
- /**
- * 缓存键值
- */
- public static final Map, String> cacheKeyMap = new HashMap<>();
- /**
- * 保存文件所在路径的key,eg.FILE_MD5:1243jkalsjflkwaejklgjawe
- */
- public static final String FILE_MD5_KEY = "FILE_MD5:";
- /**
- * 保存上传文件的状态
- */
- public static final String FILE_UPLOAD_STATUS = "FILE_UPLOAD_STATUS";
-
-
-}
diff --git a/src/main/java/win/pangniu/learn/vo/ResultVo.java b/src/main/java/win/pangniu/learn/vo/ResultVo.java
deleted file mode 100644
index 88a2b8e..0000000
--- a/src/main/java/win/pangniu/learn/vo/ResultVo.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package win.pangniu.learn.vo;
-
-/**
- * 统一返回结果pojo
- * Created by wenwen on 2017/4/23.
- * version 1.0
- */
-public class ResultVo {
-
- private ResultStatus status;
-
- private String msg;
-
- private T data;
-
- public ResultVo(ResultStatus status) {
- this(status, status.getReasonPhrase(), null);
- }
-
- public ResultVo(ResultStatus status, T data) {
- this(status, status.getReasonPhrase(), data);
- }
-
- public ResultVo(ResultStatus status, String msg, T data) {
- this.status = status;
- this.msg = msg;
- this.data = data;
- }
-
- public ResultStatus getStatus() {
- return status;
- }
-
- public void setStatus(ResultStatus status) {
- this.status = status;
- }
-
- public String getMsg() {
- return msg;
- }
-
- public void setMsg(String msg) {
- this.msg = msg;
- }
-
- public T getData() {
- return data;
- }
-
- public void setData(T data) {
- this.data = data;
- }
-
- @Override
- public String toString() {
- return "ResultVo{" +
- "status=" + status +
- ", msg='" + msg + '\'' +
- ", data=" + data +
- '}';
- }
-}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index c6a1ef0..d003a4d 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -1,20 +1,23 @@
-#开发环境
breakpoint:
upload:
dir: D:/data0/uploads/
- #1024*1024=1 048 576,5M=5 242 880
+ #1024*1024=1048576 5M=5242880
chunkSize: 5 242 880
-
spring:
redis:
host: 127.0.0.1
port: 6379
- pool:
- max-active: 30
- max-idle: 10
- max-wait: 10000
- timeout: 0
+ timeout: 300000
+ jedis:
+ pool:
+ max-idle: 30
+ min-idle: 0
+ max-active: 8
+ max-wait: -1ms
http:
+ servlet:
multipart:
- max-file-size: 5MB
+ max-file-size: 10MB
max-request-size: 100MB
+ thymeleaf:
+ cache: false
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index c230f3d..53cff54 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,26 +1,12 @@
-# Server settings (ServerProperties)
server:
port: 9090
- contextPath: /
- # Tomcat specifics
- tomcat:
- # 打开Tomcat的Access日志,并可以设置日志格式的方法
- # accessLogEnabled: false
- protocolHeader: x-forwarded-proto
- remoteIpHeader: x-forwarded-for
- basedir:
- backgroundProcessorDelay: 30
- session:
- timeout: 30 # secs
+ servlet:
+ session:
+ timeout: 30
-#log
logging:
config: classpath:logback.xml
- level: info
-# 默认的profile为dev,其他环境通过指定启动参数使用不同的profile,比如:
-# 测试环境:java -jar my-spring-boot.jar --spring.profiles.active=test
-# 生产环境:java -jar my-spring-boot.jar --spring.profiles.active=prod
spring:
profiles:
active: dev
\ No newline at end of file
diff --git a/src/main/resources/public/index.html b/src/main/resources/public/index.html
deleted file mode 100644
index f6d90c2..0000000
--- a/src/main/resources/public/index.html
+++ /dev/null
@@ -1,197 +0,0 @@
-
-
-
-
- 断点上传
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/resources/static/css/webuploader.css b/src/main/resources/static/css/webuploader.css
index 12f451f..dfb1db5 100644
--- a/src/main/resources/static/css/webuploader.css
+++ b/src/main/resources/static/css/webuploader.css
@@ -1,28 +1,34 @@
.webuploader-container {
- position: relative;
+ position: relative;
+/ / position: relative;
}
+
.webuploader-element-invisible {
- position: absolute !important;
- clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
- clip: rect(1px,1px,1px,1px);
+ position: absolute !important;
+ clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
+ clip: rect(1px, 1px, 1px, 1px);
}
+
.webuploader-pick {
- position: relative;
- display: inline-block;
- cursor: pointer;
- background: #00b7ee;
- padding: 10px 15px;
- color: #fff;
- text-align: center;
- border-radius: 3px;
- overflow: hidden;
+ position: relative;
+ display: inline-block;
+ cursor: pointer;
+ background: #00b7ee;
+ padding-left: 5px;
+ padding-right: 5px;
+/ / padding: - 5 px - 5 px;
+ color: #fff;
+ text-align: center;
+ border-radius: 3px;
+ overflow: hidden;
}
+
.webuploader-pick-hover {
- background: #00a2d4;
+ background: #00a2d4;
}
.webuploader-pick-disable {
- opacity: 0.6;
- pointer-events:none;
+ opacity: 0.6;
+ pointer-events: none;
}
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
new file mode 100644
index 0000000..af82056
--- /dev/null
+++ b/src/main/resources/templates/index.html
@@ -0,0 +1,209 @@
+
+
+
+
+ 断点上传
+
+
+
+
+
+
+
+
+
+
+
+
选择大文件
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/index2.jsp b/src/main/webapp/index2.jsp
deleted file mode 100644
index 68ec1f7..0000000
--- a/src/main/webapp/index2.jsp
+++ /dev/null
@@ -1,43 +0,0 @@
-<%@ page import="java.util.HashMap" %>
-<%@ page import="java.util.Map" %><%--
- Created by IntelliJ IDEA.
- User: wenwen
- Date: 2017/4/11
- Time: 22:03
- To change this template use File | Settings | File Templates.
---%>
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%
- // 设置请求的编码为UTF-8;
- request.setCharacterEncoding("UTF-8");
- // 设置响应的编码为UTF-8
- response.setCharacterEncoding("UTF-8");
-
- // 帐号密码数据准备
- Map accountMap = new HashMap<>();
- accountMap.put("ftpuser", "password");
-
- // 获取参数
- String userName = request.getParameter("userName");
- System.err.println(userName);
- String result;
- if (userName == null || "".equals(userName.trim())) {
- result = "{\"code\":101,\"msg\":\"参数为空\"}";
- } else {
- String password = accountMap.get(userName);
- if (password == null || "".equals(password)) {
- result = "{\"code\":102,\"msg\":\"结果为空。\"}";
- } else {
- char[] array = password.toCharArray();
- for (int i = 0; i < array.length; i++) {
- array[i] = (char) (array[i] ^ 20160831);
- }
- System.out.println("结果如下:");
- System.out.println(new String(array));//输出加密或者解密结果
- result = "{\"code\":100,\"msg\":'成功',\"data\":\"" + new String(array) + "\"}";
- }
- }
-
- // 将处理后的结果返回给客户端
- response.getWriter().write("" + result);
-%>
\ No newline at end of file
diff --git a/src/test/java/win/pangniu/learn/test/AppTest.java b/src/test/java/com/zgy/learn/test/BreakPointHttpApplicationTest.java
similarity index 85%
rename from src/test/java/win/pangniu/learn/test/AppTest.java
rename to src/test/java/com/zgy/learn/test/BreakPointHttpApplicationTest.java
index 7e9bc22..d994493 100644
--- a/src/test/java/win/pangniu/learn/test/AppTest.java
+++ b/src/test/java/com/zgy/learn/test/BreakPointHttpApplicationTest.java
@@ -1,20 +1,22 @@
-package win.pangniu.learn.test;
+package com.zgy.learn.test;
-import org.junit.Test;
+
+import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.test.context.ActiveProfiles;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLConnection;
import java.util.List;
-public class AppTest extends BaseTest {
+
+@SpringBootTest
+@ActiveProfiles(value = "dev")
+public class BreakPointHttpApplicationTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
diff --git a/src/test/java/win/pangniu/learn/test/BaseTest.java b/src/test/java/win/pangniu/learn/test/BaseTest.java
deleted file mode 100644
index c7750db..0000000
--- a/src/test/java/win/pangniu/learn/test/BaseTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package win.pangniu.learn.test;
-
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-/**
- * Created by 超文 on 2016/10/20.
- */
-// 1.4
-/*@RunWith(SpringJUnit4ClassRunner.class) // SpringJUnit支持,由此引入Spring-Test框架支持!
-//@SpringApplicationConfiguration(classes = App.class) // 指定我们SpringBoot工程的Application启动类
-//@ContextConfiguration(locations = {"classpath:spring-context-*.xml"})
-@WebAppConfiguration // 由于是Web项目,Junit需要模拟ServletContext,因此我们需要给我们的测试类加上@WebAppConfiguration。
-@SpringBootTest*/
-
-// spring boot 1.5用法
-@RunWith(SpringRunner.class)
-@SpringBootTest
-public class BaseTest {
-}