1
1
# 文件上传和下载案例
2
2
3
+ 创建一张数据表,保持上传的数据
4
+
5
+ ``` sql
6
+ CREATE TABLE "sys_upload_file " (
7
+ " id" text NOT NULL ,
8
+ " saveFolder" TEXT NOT NULL ,
9
+ " suffixName" TEXT NOT NULL ,
10
+ " filename" TEXT NOT NULL ,
11
+ PRIMARY KEY (" id" )
12
+ );
13
+ ```
14
+
15
+ 配置文件
16
+ app.properties
17
+
18
+ ``` properties
19
+ # jdbc-sqlliste
20
+ jdbc.driverClass =org.sqlite.JDBC
21
+ jdbc.url =jdbc:sqlite:D:/sqllite/student.db
22
+ jdbc.user =
23
+ jdbc.pswd =
24
+ jdbc.showSql =true
25
+ jdbc.validationQuery =select 1
3
26
```
27
+
28
+ 启动类
29
+
30
+ ``` java
31
+ package com.litongjava.tio.boo.demo.file ;
32
+
33
+ import com.litongjava.hotswap.wrapper.tio.boot.TioApplicationWrapper ;
34
+ import com.litongjava.jfinal.aop.annotation.AComponentScan ;
35
+
36
+ @AComponentScan
37
+ public class TioBootFileApp {
38
+ public static void main (String [] args ) {
39
+ long start = System . currentTimeMillis();
40
+ TioApplicationWrapper . run(TioBootFileApp . class, args);
41
+ long end = System . currentTimeMillis();
42
+ System . out. println((end - start) + " ms" );
43
+ }
44
+ }
45
+
46
+ ```
47
+
48
+ 配置类
49
+
50
+ ``` java
51
+ package com.litongjava.tio.boo.demo.file.config ;
52
+
53
+ import javax.sql.DataSource ;
54
+
55
+ import com.alibaba.druid.pool.DruidDataSource ;
56
+ import com.jfinal.template.Engine ;
57
+ import com.jfinal.template.source.ClassPathSourceFactory ;
58
+ import com.litongjava.jfinal.aop.annotation.AConfiguration ;
59
+ import com.litongjava.jfinal.aop.annotation.AInitialization ;
60
+ import com.litongjava.jfinal.plugin.activerecord.ActiveRecordPlugin ;
61
+ import com.litongjava.jfinal.plugin.activerecord.OrderedFieldContainerFactory ;
62
+ import com.litongjava.jfinal.plugin.activerecord.dialect.Sqlite3Dialect ;
63
+ import com.litongjava.jfinal.plugin.hikaricp.DsContainer ;
64
+ import com.litongjava.tio.boot.constatns.ConfigKeys ;
65
+ import com.litongjava.tio.boot.server.TioBootServer ;
66
+ import com.litongjava.tio.utils.environment.EnvironmentUtils ;
67
+
68
+ @AConfiguration
69
+ public class TableToJsonConfig {
70
+
71
+ /**
72
+ * create datasource
73
+ * @return
74
+ */
75
+ @AInitialization (priority = 10 )
76
+ public DataSource dataSource () {
77
+ // get parameter from config file
78
+ String jdbcUrl = EnvironmentUtils . get(" jdbc.url" );
79
+ String jdbcUser = EnvironmentUtils . get(" jdbc.user" );
80
+ String jdbcPswd = EnvironmentUtils . get(" jdbc.pswd" );
81
+ String jdbcValidationQuery = EnvironmentUtils . get(" jdbc.validationQuery" );
82
+
83
+ // create datasource
84
+ DruidDataSource druidDataSource = new DruidDataSource ();
85
+
86
+ // set basic parameter
87
+ druidDataSource. setUrl(jdbcUrl);
88
+ druidDataSource. setUsername(jdbcUser);
89
+ druidDataSource. setPassword(jdbcPswd);
90
+ druidDataSource. setValidationQuery(jdbcValidationQuery);
91
+ // save datasource
92
+ DsContainer . setDataSource(druidDataSource);
93
+ // close datasource while server close
94
+ TioBootServer . me(). addDestroyMethod(druidDataSource:: close);
95
+ return druidDataSource;
96
+ }
97
+
98
+ /**
99
+ * create ActiveRecordPlugin
100
+ * @return
101
+ * @throws Exception
102
+ */
103
+ @AInitialization
104
+ public ActiveRecordPlugin activeRecordPlugin () throws Exception {
105
+ // get datasource from DsContainer
106
+ DataSource dataSource = DsContainer . ds;
107
+
108
+ // get parameter from config file
109
+ Boolean tioDevMode = EnvironmentUtils . getBoolean(ConfigKeys . TIO_DEV_MODE , false );
110
+ boolean jdbcShowSql = EnvironmentUtils . getBoolean(" jdbc.showSql" , false );
111
+ // cretae plugin
112
+ ActiveRecordPlugin arp = new ActiveRecordPlugin (dataSource);
113
+ // set parameter
114
+ arp. setDialect(new Sqlite3Dialect ());
115
+ arp. setContainerFactory(new OrderedFieldContainerFactory ());
116
+ arp. setShowSql(jdbcShowSql);
117
+
118
+ if (tioDevMode) {
119
+ arp. setDevMode(true );
120
+ }
121
+
122
+ // config engine
123
+ Engine engine = arp. getEngine();
124
+ engine. setSourceFactory(new ClassPathSourceFactory ());
125
+ engine. setCompressorOn(' ' );
126
+ engine. setCompressorOn(' \n ' );
127
+ // arp.addSqlTemplate("/sql/all_sqls.sql");
128
+ // start plugin
129
+ arp. start();
130
+ // close plugin while server close
131
+ TioBootServer . me(). addDestroyMethod(arp:: stop);
132
+ return arp;
133
+ }
134
+ }
135
+ ```
136
+
137
+ 实体类
138
+
139
+ ```
140
+ package com.litongjava.tio.boo.demo.file.model;
141
+
4
142
import java.io.File;
5
143
6
144
import lombok.AllArgsConstructor;
@@ -11,33 +149,57 @@ import lombok.NoArgsConstructor;
11
149
@NoArgsConstructor
12
150
@AllArgsConstructor
13
151
public class FileSaveResult {
14
- private String docId ;
152
+ private String id ;
15
153
private String saveFolder;
16
154
private String suffixName;
155
+ private String filename;
17
156
private File file;
18
157
}
19
158
```
20
159
160
+ 常量类
161
+
162
+ - UPlOAD_FOLDER_NAME 保持文件上传路径
163
+
164
+ ```
165
+ package com.litongjava.tio.boo.demo.file.constants;
166
+
167
+ public interface AppConstants {
168
+ String UPlOAD_FOLDER_NAME = "upload";
169
+ }
170
+
21
171
```
22
- package com.litongjava.hopto.translation.service;
172
+
173
+ service
174
+
175
+ ``` java
176
+ package com.litongjava.tio.boo.demo.file.services ;
23
177
24
178
import java.io.File ;
25
179
import java.io.IOException ;
180
+ import java.util.UUID ;
26
181
27
- import com.litongjava.hopto.translation.constants.AppConstants;
28
- import com.litongjava.hopto.translation.model.FileSaveResult;
182
+ import com.litongjava.data.services.DbJsonService ;
183
+ import com.litongjava.jfinal.aop.annotation.AAutowired ;
184
+ import com.litongjava.jfinal.plugin.activerecord.Db ;
185
+ import com.litongjava.jfinal.plugin.activerecord.Record ;
186
+ import com.litongjava.tio.boo.demo.file.constants.AppConstants ;
187
+ import com.litongjava.tio.boo.demo.file.model.FileSaveResult ;
29
188
import com.litongjava.tio.utils.hutool.FileUtil ;
30
189
31
- import cn.hutool.core.lang.UUID;
32
190
import lombok.extern.slf4j.Slf4j ;
33
191
34
192
@Slf4j
35
193
public class FileService {
194
+ @AAutowired
195
+ private DbJsonService dbJsonService;
36
196
37
197
public FileSaveResult save (String filename , byte [] fileData ) {
38
- String newFilename = UUID.fastUUID().toString();
198
+ String newFilename = UUID . randomUUID(). toString();
199
+
39
200
FileSaveResult fileSaveResult = new FileSaveResult ();
40
- fileSaveResult.setDocId(newFilename);
201
+ fileSaveResult. setId(newFilename);
202
+ fileSaveResult. setFilename(filename);
41
203
42
204
int lastIndexOf = filename. lastIndexOf(" ." );
43
205
if (lastIndexOf > 0 ) {
@@ -56,21 +218,151 @@ public class FileService {
56
218
fileSaveResult. setSaveFolder(AppConstants . UPlOAD_FOLDER_NAME );
57
219
log. info(" newFilename:{}" , newFilename);
58
220
221
+ // save to folder
59
222
File file = new File (newFilename);
60
223
try {
61
224
FileUtil . writeBytes(fileData, file);
225
+ fileSaveResult. setFile(file);
62
226
} catch (IOException e) {
63
- e.printStackTrace( );
227
+ throw new RuntimeException (e );
64
228
}
65
- fileSaveResult.setFile(file);
66
229
230
+ // save to db
231
+ // vresion 1
232
+ Record record = new Record ();
233
+ record. set(" id" , fileSaveResult. getId());
234
+ record. set(" saveFolder" , fileSaveResult. getSaveFolder());
235
+ record. set(" suffixName" , fileSaveResult. getSuffixName());
236
+ record. set(" filename" , filename);
237
+ // version 2 test fail
238
+ // Record record = Record.fromBean(fileSaveResult);
239
+ boolean save = Db . save(" sys_upload_file" , record);
240
+ if (save) {
241
+ return fileSaveResult;
242
+ } else {
243
+ log. error(" save file error:{}" , filename);
244
+ }
67
245
return fileSaveResult;
68
246
}
69
247
70
248
public File getUploadFile (FileSaveResult result ) {
71
- String filename = result.getSaveFolder() + "/" + result.getDocId () + result.getSuffixName();
249
+ String filename = result. getSaveFolder() + " /" + result. getId () + result. getSuffixName();
72
250
return new File (filename);
73
251
}
252
+
253
+ public File getUploadFile (String id ) {
254
+ Record record = Db . findById(" sys_upload_file" , id);
255
+ FileSaveResult fileSaveResult = record. toBean(FileSaveResult . class);
256
+ log. info(" select from db:{}" ,fileSaveResult);
257
+ return getUploadFile(fileSaveResult);
258
+ }
259
+ }
260
+
261
+ ```
262
+
263
+ controller
264
+
265
+ ``` java
266
+ package com.litongjava.tio.boo.demo.file.controller ;
267
+
268
+ import java.io.File ;
269
+ import java.io.FileInputStream ;
270
+ import java.io.IOException ;
271
+ import java.io.InputStream ;
272
+
273
+ import com.litongjava.jfinal.aop.annotation.AAutowired ;
274
+ import com.litongjava.tio.boo.demo.file.model.FileSaveResult ;
275
+ import com.litongjava.tio.boo.demo.file.services.FileService ;
276
+ import com.litongjava.tio.http.common.HttpRequest ;
277
+ import com.litongjava.tio.http.common.HttpResponse ;
278
+ import com.litongjava.tio.http.common.UploadFile ;
279
+ import com.litongjava.tio.http.server.annotation.RequestPath ;
280
+ import com.litongjava.tio.http.server.util.Resps ;
281
+ import com.litongjava.tio.utils.resp.RespVo ;
282
+
283
+ import lombok.Cleanup ;
284
+ import lombok.extern.slf4j.Slf4j ;
285
+
286
+ @RequestPath (" /file" )
287
+ @Slf4j
288
+ public class FileController {
289
+
290
+ @AAutowired
291
+ private FileService fileService;
292
+
293
+ public String index () {
294
+ return " index" ;
295
+ }
296
+
297
+ /**
298
+ * upload file
299
+ * @param file
300
+ * @return
301
+ */
302
+ public RespVo upload (UploadFile file ) {
303
+ if (file != null ) {
304
+ String name = file. getName();
305
+ byte [] fileData = file. getData();
306
+ // save file
307
+ FileSaveResult fileSaveResult = fileService. save(name, fileData);
308
+ fileSaveResult. setFile(null );
309
+
310
+ log. info(" save file finished" );
311
+ return RespVo . ok(fileSaveResult);
312
+
313
+ }
314
+ return RespVo . fail(" fail" ). code(- 1 );
315
+ }
316
+
317
+ @RequestPath (" /download/{id}" )
318
+ public HttpResponse download (HttpRequest request , String id ) {
319
+ log. info(" id:{}" , id);
320
+ File file = fileService. getUploadFile(id);
321
+ int available;
322
+ try {
323
+ @Cleanup
324
+ InputStream inputStream = new FileInputStream (file);
325
+ available = inputStream. available();
326
+ byte [] fileBytes = new byte [available];
327
+ inputStream. read(fileBytes, 0 , available);
328
+ String contentType = " application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=utf-8" ;
329
+ HttpResponse response = Resps . bytesWithContentType(request, fileBytes, contentType);
330
+ return response;
331
+ } catch (IOException e) {
332
+ e. printStackTrace();
333
+ return Resps . json(request, RespVo . fail(" Error generating captcha" ));
334
+ }
335
+ }
74
336
}
337
+ ```
338
+
339
+ 上传文件
340
+ 请求示例
341
+
342
+ ``` shell
343
+ curl --location --request POST ' http://localhost/file/upload' \
344
+ --header ' User-Agent: Apifox/1.0.0 (https://apifox.com)' \
345
+ --form ' file=@"test-chinese.docx"'
346
+ ```
347
+
348
+ 响应示例
75
349
350
+ ``` json
351
+ {
352
+ "data" : {
353
+ "file" : null ,
354
+ "docId" : " 6632a4ba-ae03-4f05-adce-de6acdd5c560" ,
355
+ "saveFolder" : " upload" ,
356
+ "suffixName" : " .docx" ,
357
+ "filename" : " test-chinese.docx"
358
+ },
359
+ "ok" : true ,
360
+ "code" : null ,
361
+ "msg" : null
362
+ }
76
363
```
364
+
365
+ 下载
366
+
367
+ - http://localhost/file/download/6632a4ba-ae03-4f05-adce-de6acdd5c560
368
+ - 下载文件
0 commit comments