1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import static utils.FileUtils.generateFileName;
import static utils.UploadUtils.*;
/**
* 上传文件
* @param md5
* @param file
*/
public void upload(String name,
String md5,
MultipartFile file) throws IOException {
String path = UploadConfig.path + generateFileName();
FileUtils.write(path, file.getInputStream());
fileDao.save(new File(name, md5, path, new Date()));
}

/**
* 分块上传文件
* @param md5
* @param size
* @param chunks
* @param chunk
* @param file
* @throws IOException
*/
public void uploadWithBlock(String name,
String md5,
Long size,
Integer chunks,
Integer chunk,
MultipartFile file) throws IOException {
// 获取文件名称 用md5 跟 分块总数量作为map 存储为了后面上传准备
String fileName = getFileName(md5, chunks);
// 获取yml 中存储的配置路径, size 文件大小, inputstream 文件流 file.getSize() 分块大小, chunks 总分块数量, chunk 当前那个分块
FileUtils.writeWithBlok(UploadConfig.path + fileName, size, file.getInputStream(), file.getSize(), chunks, chunk);
// 添加上传的分块记录, 判断哪些分块已经成功上传
addChunk(md5,chunk);
// 判断是否完成全部分块上传
if (isUploaded(md5)) {
// 从map中删除该md5信息
removeKey(md5);
// 存储对应数据
fileDao.save(new File(name, md5,UploadConfig.path + fileName, new Date()));
}
}

/**
* 检查Md5判断文件是否已上传
* @param md5
* @return
*/
public boolean checkMd5(String md5) {
File file = new File();
file.setMd5(md5);
return fileDao.getByFile(file) == null;
}


FileUtils 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package cn.attackme.myuploader.utils;


import java.io.*;
import java.util.UUID;

/**
* 文件操作工具类
*/
public class FileUtils {

/**
* 写入文件
* @param target
* @param src
* @throws IOException
*/
public static void write(String target, InputStream src) throws IOException {
OutputStream os = new FileOutputStream(target);
byte[] buf = new byte[1024];
int len;
while (-1 != (len = src.read(buf))) {
os.write(buf,0,len);
}
os.flush();
os.close();
}

/**
* 分块写入文件
* @param target
* @param targetSize
* @param src
* @param srcSize
* @param chunks
* @param chunk
* @throws IOException
*/
public static void writeWithBlok(String target, Long targetSize, InputStream src, Long srcSize, Integer chunks, Integer chunk) throws IOException {
//配置文件读写确定文件名
RandomAccessFile randomAccessFile = new RandomAccessFile(target,"rw");
// 文件总大小
randomAccessFile.setLength(targetSize);
if (chunk == chunks - 1) {
// 指定位置开始读
randomAccessFile.seek(targetSize - srcSize);
} else {
// 所有分块合并一起的位置
randomAccessFile.seek(chunk * srcSize);
}
byte[] buf = new byte[1024];
int len;
// 分段写入
while (-1 != (len = src.read(buf))) {
randomAccessFile.write(buf,0,len);
}
randomAccessFile.close();
}

/**
* 生成随机文件名
* @return
*/
public static String generateFileName() {
return UUID.randomUUID().toString();
}
}

UploadUtils 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package cn.attackme.myuploader.utils;

import java.util.HashMap;
import java.util.Map;

import static cn.attackme.myuploader.utils.FileUtils.generateFileName;

/**
* 分块上传工具类
*/
public class UploadUtils {
/**
* 内部类记录分块上传文件信息
*/
private static class Value {
String name;
boolean[] status;

Value(int n) {
this.name = generateFileName();
this.status = new boolean[n];
}
}

private static Map<String, Value> chunkMap = new HashMap<>();

/**
* 判断文件所有分块是否已上传
* @param key
* @return
*/
public static boolean isUploaded(String key) {
if (isExist(key)) {
for (boolean b : chunkMap.get(key).status) {
if (!b) {
return false;
}
}
return true;
}
return false;
}

/**
* 判断文件是否有分块已上传
* @param key
* @return
*/
private static boolean isExist(String key) {
return chunkMap.containsKey(key);
}

/**
* 为文件添加上传分块记录
* @param key
* @param chunk
*/
public static void addChunk(String key, int chunk) {
chunkMap.get(key).status[chunk] = true;
}

/**
* 从map中删除键为key的键值对
* @param key
*/
public static void removeKey(String key) {
if (isExist(key)) {
chunkMap.remove(key);
}
}

/**
* 获取随机生成的文件名
* @param key
* @param chunks
* @return
*/
public static String getFileName(String key, int chunks) {
if (!isExist(key)) {
synchronized (UploadUtils.class) {
if (!isExist(key)) {
chunkMap.put(key, new Value(chunks));
}
}
}
return chunkMap.get(key).name;
}
}

UploadConfig 类

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class UploadConfig {
public static String path;

public UploadConfig() {
}

@Value("${upload.path}")
public void setPath(String path) {
UploadConfig.path = path;
}
}