使用html5的api来上传文件夹,只有chrome支持。

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input id="upload" type='file' name="file" webkitdirectory>
<button id="button">按钮</button>
</body>
<script src="//libs.useso.com/js/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function Map() {
/**
* 结构
* @param key
* @param value
*/
function Struct(key, value) {
this.key = key;
this.value = value;
}

/**
* 数据存放数组
*/
this.arr = [];
/**
* 增加数据
* @param key {String}
* @param value {Object}
*/
this.put = function (key, value) {
for (var i = 0; i < this.arr.length; i++) {
if (this.arr[i].key === key) {
this.arr[i].value = value;
return;
}
}
this.arr[this.arr.length] = new Struct(key, value);
};
/**
* 通过key获取数据
* @param key {String}
* @returns {Object}
*/
this.get = function (key) {
for (var i = 0; i < this.arr.length; i++) {
if (this.arr[i].key === key) {
return this.arr[i].value;
}
}
return null;
};
/**
* 删除数据
* @param key{String}
*/
this.remove = function (key) {
var v;
for (var i = 0; i < this.arr.length; i++) {
v = this.arr[i];
if (v.key === key) {
this.arr.splice(i, 1);
return;
}
}
};
/**
* 是否存在key
* @param key {String}
* @returns {boolean}
*/
this.containsKey = function (key) {
var v;
for (var i = 0; i < this.arr.length; i++) {
v = this.arr[i];
if (v.key === key) {
return true;
}
}
return false;
};
/**
* 获取map数据量
* @returns {Number}
*/
this.size = function () {
return this.arr.length;
};
/**
* 判断Map是否为空
* @returns {boolean}
*/
this.isEmpty = function () {
return this.arr.length <= 0;
};
/**
* 全部清空
*/
this.removeAll = function () {
this.arr = [];
};
}
</script>
<script type="text/javascript">
var host = "http://example.com"; // 远程服务器地址
var map = new Map(); // 用来存放文件夹路径和id的键值对
var files = [];

$("#upload").change(function () {
files = this.files;
console.log(files);
});

$("#button").on("click", function () {
for (var i = 0; i < files.length; i++) {
var file = files[i];
console.log(file);
var path = getFolder(file.webkitRelativePath);
var folderId = getFolderIdFromMap(path);
// 创建文件
uploadResource(file, folderId, 10001);
}
});

function uploadResource(file, folderId, projectId) {
var filepath = null;
var formData = new FormData();
formData.append("text", file);
$.ajax({
url: host + "/sys/upload/uploadProjectResource",
type: "POST",
data: formData,
xhrFields: {
withCredentials: true // 确保请求会携带上Cookie
},
enctype: 'multipart/form-data',
processData: false, // tell jQuery not to process the data
contentType: false,
complete: function (respResult) {
if (respResult.status == 200) {
filepath = respResult.responseText;
$.ajax({
url: host + "/project/resource/create",
type: "post",
dataType: "json",
xhrFields: {
withCredentials: true
},
beforeSend: function (xhr) {
xhr.setRequestHeader("Content-Type", "application/json");
},
data: JSON.stringify({
"projectId": projectId,
"resourceContent": filepath,
"resourceName": file.name,
"folderId": folderId,
"type": 20 // 当前是文件资源
}),
success: function (data) {
console.log(data);
},
error: function (respResult) {
}
});
} else {
}
}
});
}

function getFolderIdFromMap(path) {
var folderId = map.get(path);
var folderName = path.substring(path.lastIndexOf("/") + 1, path.length);
var localFolder = 0;
if (path.indexOf("/") > 0) {
// 说明当前不是最高级目录,是子目录
localFolder = getFolderIdFromMap(path.substring(0, path.lastIndexOf("/")));
}
if (folderId == null) {
$.ajax({
async: false,
url: host + "/project/resource/create/folder",
type: "post",
dataType: "json",
xhrFields: {
withCredentials: true
},
beforeSend: function (xhr) {
xhr.setRequestHeader("Content-Type", "application/json");
},
data: JSON.stringify({
"projectId": 10001,
"folderName": folderName,
"folderId": localFolder
}),
success: function (data) {
console.log(data);
folderId = data.id;
map.put(path, folderId);
},
error: function (respResult) {
}
});
}
return folderId;
}

function getFolder(path) {
console.log(path);
var index = path.lastIndexOf("/");
return path.substring(0, index);
}
</script>

</html>

服务器采用java,用了接受文件和创建文件夹。
文件夹也是虚拟的,采用在当前记录增加parentId来存储父节点,实现树的结构。
表结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE t_project_resource_folder
(
id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
folder_name VARCHAR(255) DEFAULT '' COMMENT '文件夹名',
parent_id BIGINT(20) DEFAULT '0' NOT NULL COMMENT '父文件夹id,0表示顶级目录'
)
CREATE TABLE t_project_resource
(
id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
resource_name VARCHAR(255) NOT NULL COMMENT '资源名',
resource_content VARCHAR(255) COMMENT '资源内容,通常是放在oss文件的url',
resource_folder_id BIGINT(20) DEFAULT '0' COMMENT '资源文件夹ID,0表示文件处于顶级目录'
)

服务器端接口的代码:

1
2
3
4
5
6
7
8
9
@RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<String> upload(MultipartFile text) throws Exception {
String fileName = text.getOriginalFilename();
int lastDot = fileName.lastIndexOf(".");
String type = fileName.substring(lastDot + 1);
String sb = "uploads" + "/" + UUID.randomUUID().toString() + "." + type;
String uploadPath = storageProvider.upload(sb, text); // 调用service接口把文件存到oss中,返回文件在oss的地址
return ResponseEntity.ok(uploadPath);
}