Skip to content

Commit 919423c

Browse files
author
litongjava
committed
add fileuplod demo
1 parent b8b62c6 commit 919423c

File tree

2 files changed

+303
-11
lines changed

2 files changed

+303
-11
lines changed

docs/.vuepress/config/sidebar-zh.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,6 @@
177177
{
178178
"title": "99_案例",
179179
"collapsable": false,
180-
"children": ["99_案例/01.md", "99_案例/02.md"]
180+
"children": ["99_案例/01.md", "99_案例/02.md", "99_案例/03.md"]
181181
}
182182
]

docs/zh/99_案例/03.md

+302-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,144 @@
11
# 文件上传和下载案例
22

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
326
```
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+
4142
import java.io.File;
5143
6144
import lombok.AllArgsConstructor;
@@ -11,33 +149,57 @@ import lombok.NoArgsConstructor;
11149
@NoArgsConstructor
12150
@AllArgsConstructor
13151
public class FileSaveResult {
14-
private String docId;
152+
private String id;
15153
private String saveFolder;
16154
private String suffixName;
155+
private String filename;
17156
private File file;
18157
}
19158
```
20159

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+
21171
```
22-
package com.litongjava.hopto.translation.service;
172+
173+
service
174+
175+
```java
176+
package com.litongjava.tio.boo.demo.file.services;
23177

24178
import java.io.File;
25179
import java.io.IOException;
180+
import java.util.UUID;
26181

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;
29188
import com.litongjava.tio.utils.hutool.FileUtil;
30189

31-
import cn.hutool.core.lang.UUID;
32190
import lombok.extern.slf4j.Slf4j;
33191

34192
@Slf4j
35193
public class FileService {
194+
@AAutowired
195+
private DbJsonService dbJsonService;
36196

37197
public FileSaveResult save(String filename, byte[] fileData) {
38-
String newFilename = UUID.fastUUID().toString();
198+
String newFilename = UUID.randomUUID().toString();
199+
39200
FileSaveResult fileSaveResult = new FileSaveResult();
40-
fileSaveResult.setDocId(newFilename);
201+
fileSaveResult.setId(newFilename);
202+
fileSaveResult.setFilename(filename);
41203

42204
int lastIndexOf = filename.lastIndexOf(".");
43205
if (lastIndexOf > 0) {
@@ -56,21 +218,151 @@ public class FileService {
56218
fileSaveResult.setSaveFolder(AppConstants.UPlOAD_FOLDER_NAME);
57219
log.info("newFilename:{}", newFilename);
58220

221+
// save to folder
59222
File file = new File(newFilename);
60223
try {
61224
FileUtil.writeBytes(fileData, file);
225+
fileSaveResult.setFile(file);
62226
} catch (IOException e) {
63-
e.printStackTrace();
227+
throw new RuntimeException(e);
64228
}
65-
fileSaveResult.setFile(file);
66229

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+
}
67245
return fileSaveResult;
68246
}
69247

70248
public File getUploadFile(FileSaveResult result) {
71-
String filename = result.getSaveFolder() + "/" + result.getDocId() + result.getSuffixName();
249+
String filename = result.getSaveFolder() + "/" + result.getId() + result.getSuffixName();
72250
return new File(filename);
73251
}
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+
}
74336
}
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+
响应示例
75349

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+
}
76363
```
364+
365+
下载
366+
367+
- http://localhost/file/download/6632a4ba-ae03-4f05-adce-de6acdd5c560
368+
- 下载文件

0 commit comments

Comments
 (0)