Browse Source

新增文件上传,下载

zhouhao 7 years ago
parent
commit
8523d70410
21 changed files with 1141 additions and 65 deletions
  1. 42 0
      hsweb-system/hsweb-system-file/hsweb-system-file-controller/pom.xml
  2. 239 0
      hsweb-system/hsweb-system-file/hsweb-system-file-controller/src/main/java/org/hswebframework/web/controller/file/FileController.java
  3. 35 0
      hsweb-system/hsweb-system-file/hsweb-system-file-controller/src/main/java/org/hswebframework/web/controller/file/FileInfoController.java
  4. 27 0
      hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-api/pom.xml
  5. 11 0
      hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-api/src/main/java/org/hswebframework/web/dao/file/FileInfoDao.java
  6. 26 0
      hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-mybatis/pom.xml
  7. 53 0
      hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-mybatis/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/file/FileInfoMapper.xml
  8. 18 0
      hsweb-system/hsweb-system-file/hsweb-system-file-dao/pom.xml
  9. 22 0
      hsweb-system/hsweb-system-file/hsweb-system-file-entity/pom.xml
  10. 115 0
      hsweb-system/hsweb-system-file/hsweb-system-file-entity/src/main/java/org/hswebframework/web/entity/file/FileInfoEntity.java
  11. 147 0
      hsweb-system/hsweb-system-file/hsweb-system-file-entity/src/main/java/org/hswebframework/web/entity/file/SimpleFileInfoEntity.java
  12. 12 1
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/pom.xml
  13. 0 27
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/src/main/java/org/hswebframework/web/service/file/FileInfo.java
  14. 13 0
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/src/main/java/org/hswebframework/web/service/file/FileInfoService.java
  15. 42 3
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/src/main/java/org/hswebframework/web/service/file/FileService.java
  16. 4 9
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/pom.xml
  17. 126 25
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/src/main/java/org/hswebframework/web/service/file/LocalFileService.java
  18. 79 0
      hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/src/main/java/org/hswebframework/web/service/file/simple/SimpleFileInfoService.java
  19. 78 0
      hsweb-system/hsweb-system-file/hsweb-system-file-starter/pom.xml
  20. 48 0
      hsweb-system/hsweb-system-file/hsweb-system-file-starter/src/main/resources/hsweb-starter.js
  21. 4 0
      hsweb-system/hsweb-system-file/pom.xml

+ 42 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-controller/pom.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-file</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file-controller</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-service-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-controller</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework</groupId>
+            <artifactId>hsweb-expands-compress</artifactId>
+            <version>${hsweb.expands.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 239 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-controller/src/main/java/org/hswebframework/web/controller/file/FileController.java

@@ -0,0 +1,239 @@
+package org.hswebframework.web.controller.file;
+
+import com.alibaba.fastjson.JSON;
+import org.hswebframework.expands.compress.Compress;
+import org.hswebframework.expands.compress.zip.ZIPWriter;
+import org.hswebframework.utils.StringUtils;
+import org.hswebframework.web.NotFoundException;
+import org.hswebframework.web.authorization.Authentication;
+import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.controller.message.ResponseMessage;
+import org.hswebframework.web.entity.file.FileInfoEntity;
+import org.hswebframework.web.logging.AccessLogger;
+import org.hswebframework.web.service.file.FileInfoService;
+import org.hswebframework.web.service.file.FileService;
+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.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.activation.MimetypesFileTypeMap;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@RestController
+@RequestMapping("${hsweb.web.mappings.file:file}")
+@Authorize(permission = "file")
+@AccessLogger("文件")
+public class FileController {
+
+    private String staticFilePath = "./static";
+
+    private String staticLocation = "/";
+
+    @Value("${hsweb.web.upload.staticFilePath:./static}")
+    public void setStaticFilePath(String staticFilePath) {
+        this.staticFilePath = staticFilePath;
+    }
+
+    @Value("${hsweb.web.upload.staticLocation:/}")
+    public void setStaticLocation(String staticLocation) {
+        this.staticLocation = staticLocation;
+    }
+
+    private FileService fileService;
+
+    private FileInfoService fileInfoService;
+
+    private Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    private static final Pattern fileNameKeyWordPattern = Pattern.compile("(\\\\)|(/)|(:)(|)|(\\?)|(>)|(<)|(\")");
+
+    @Autowired
+    public void setFileService(FileService fileService) {
+        this.fileService = fileService;
+    }
+
+    @Autowired
+    public void setFileInfoService(FileInfoService fileInfoService) {
+        this.fileInfoService = fileInfoService;
+    }
+
+    /**
+     * 构建并下载zip文件.仅支持POST请求
+     *
+     * @param name     文件名
+     * @param dataStr  数据,jsonArray. 格式:[{"name":"fileName","text":"fileText"}]
+     * @param response {@link HttpServletResponse}
+     * @throws IOException      写出zip文件错误
+     * @throws RuntimeException 构建zip文件错误
+     */
+    @RequestMapping(value = "/download-zip/{name:.+}", method = {RequestMethod.POST})
+    @AccessLogger("下载zip文件")
+    @Authorize(action = "download")
+    public void downloadZip(@PathVariable("name") String name,
+                            @RequestParam("data") String dataStr,
+                            HttpServletResponse response) throws IOException {
+        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(name, "utf-8"));
+        ZIPWriter writer = Compress.zip();
+        List<Map<String, String>> data = (List) JSON.parseArray(dataStr, Map.class);
+        data.forEach(map -> writer.addTextFile(map.get("name"), map.get("text")));
+        writer.write(response.getOutputStream());
+    }
+
+    /**
+     * 构建一个文本文件,并下载.支持GET,POST请求
+     *
+     * @param name     文件名
+     * @param text     文本内容
+     * @param response {@link HttpServletResponse}
+     * @throws IOException 写出文本内容错误
+     */
+    @RequestMapping(value = "/download-text/{name:.+}", method = {RequestMethod.GET, RequestMethod.POST})
+    @AccessLogger("下载text文件")
+    @Authorize(action = "download")
+    public void downloadTxt(@PathVariable("name") String name,
+                            @RequestParam("text") String text,
+                            HttpServletResponse response) throws IOException {
+        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(name, "utf-8"));
+        response.getWriter().write(text);
+    }
+
+    /**
+     * 使用restful风格,通过文件ID下载已经上传的文件,支持断点下载
+     * 如: http://host:port/file/download/aSk2a/file.zip 将下载 ID为aSk2a的文件.并命名为file.zip
+     *
+     * @param id       文件ID
+     * @param name     文件名
+     * @param response {@link HttpServletResponse}
+     * @param request  {@link HttpServletRequest}
+     * @return 下载结果, 在下载失败时, 将返回错误信息
+     * @throws IOException       读写文件错误
+     * @throws NotFoundException 文件不存在
+     */
+    @RequestMapping(value = "/download/{id}/{name:.+}", method = RequestMethod.GET)
+    @AccessLogger("下载文件")
+    @Authorize(action = "download")
+    public void restDownLoad(@PathVariable("id") String id,
+                             @PathVariable("name") String name,
+                             HttpServletResponse response,
+                             HttpServletRequest request) throws IOException {
+        downLoad(id, name, response, request);
+    }
+
+    /**
+     * 通过文件ID下载已经上传的文件,支持断点下载
+     * 如: http://host:port/file/download/aSk2a/file.zip 将下载 ID为aSk2a的文件.并命名为file.zip
+     *
+     * @param id       要下载资源文件的id
+     * @param name     自定义文件名,该文件名不能存在非法字符.如果此参数为空(null).将使用文件上传时的文件名
+     * @param response {@link javax.servlet.http.HttpServletResponse}
+     * @param request  {@link javax.servlet.http.HttpServletRequest}
+     * @return 下载结果, 在下载失败时, 将返回错误信息
+     * @throws IOException                              读写文件错误
+     * @throws org.hswebframework.web.NotFoundException 文件不存在
+     */
+    @GetMapping(value = "/download/{id}")
+    @AccessLogger("下载文件")
+    @Authorize(action = "download")
+    public void downLoad(@PathVariable("id") String id,
+                         @RequestParam(value = "name", required = false) String name,
+                         HttpServletResponse response, HttpServletRequest request)
+            throws IOException {
+        FileInfoEntity fileInfo = fileInfoService.selectByPk(id);
+        if (fileInfo == null || fileInfo.getStatus() != 1) {
+            throw new NotFoundException("文件不存在");
+        }
+        String fileName = fileInfo.getName();
+
+        String suffix = fileName.contains(".") ?
+                fileName.substring(fileName.lastIndexOf("."), fileName.length()) :
+                "";
+        //获取contentType
+        String contentType = fileInfo.getType() == null ?
+                MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(fileName) :
+                fileInfo.getType();
+        //未自定义文件名,则使用上传时的文件名
+        if (StringUtils.isNullOrEmpty(name))
+            name = fileInfo.getName();
+        //如果未指定文件拓展名,则追加默认的文件拓展名
+        if (!name.contains("."))
+            name = name.concat(".").concat(suffix);
+        //关键字剔除
+        name = fileNameKeyWordPattern.matcher(name).replaceAll("");
+        int skip = 0;
+        long fSize = fileInfo.getSize();
+        //尝试判断是否为断点下载
+        try {
+            //获取要继续下载的位置
+            String Range = request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-", "");
+            skip = StringUtils.toInt(Range);
+        } catch (Exception e) {
+        }
+        response.setContentLength((int) fSize);//文件大小
+        response.setContentType(contentType);
+        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(name, "utf-8"));
+        //断点下载
+        if (skip > 0) {
+            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+            String contentRange = "bytes " + skip + "-" + (fSize - 1) + "/" + fSize;
+            response.setHeader("Content-Range", contentRange);
+        }
+        fileService.writeFile(id, response.getOutputStream(), skip);
+    }
+
+    /**
+     * 上传文件,支持多文件上传.获取到文件流后,调用{@link org.hswebframework.web.service.file.FileService#saveFile(InputStream, String, String, String)}进行文件保存
+     * 上传成功后,将返回资源信息如:[{"id":"fileId","name":"fileName","md5":"md5"}]
+     *
+     * @param files 文件列表
+     * @return 文件上传结果.
+     * @throws IOException 保存文件错误
+     */
+    @PostMapping(value = "/upload")
+    @AccessLogger("上传文件")
+    @Authorize(action = "upload")
+    public ResponseMessage<List<FileInfoEntity>> upload(MultipartFile[] files) throws IOException {
+        if (logger.isInfoEnabled())
+            logger.info(String.format("start upload , file number:%s", files.length));
+        List<FileInfoEntity> resourcesList = new LinkedList<>();
+        Authentication authentication = Authentication.current().orElseThrow(null);
+        String creator = authentication == null ? null : authentication.getUser().getId();
+        for (MultipartFile file : files) {
+            if (!file.isEmpty()) {
+                if (logger.isInfoEnabled())
+                    logger.info("start write file:{}", file.getOriginalFilename());
+                String fileName = file.getOriginalFilename();
+                FileInfoEntity resources = fileService.saveFile(file.getInputStream(), fileName, file.getContentType(), creator);
+                resourcesList.add(resources);
+            }
+        }//响应上传成功的资源信息
+        return ResponseMessage.ok(resourcesList)
+                .include(FileInfoEntity.class, FileInfoEntity.id, FileInfoEntity.name, FileInfoEntity.id);
+    }
+
+    @PostMapping(value = "/upload-static")
+    @AccessLogger("上传静态文件")
+    @Authorize(action = "static")
+    public ResponseMessage<String> uploadStatic(MultipartFile file) throws IOException {
+        if (file.isEmpty()) return ResponseMessage.ok();
+        return ResponseMessage.ok(fileService.saveStaticFile(file.getInputStream(), file.getOriginalFilename()));
+    }
+}

+ 35 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-controller/src/main/java/org/hswebframework/web/controller/file/FileInfoController.java

@@ -0,0 +1,35 @@
+package org.hswebframework.web.controller.file;
+
+import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.commons.entity.param.QueryParamEntity;
+import org.hswebframework.web.controller.SimpleGenericEntityController;
+import org.hswebframework.web.entity.file.FileInfoEntity;
+import org.hswebframework.web.logging.AccessLogger;
+import org.hswebframework.web.service.file.FileInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 文件信息
+ *
+ * @author hsweb-generator-online
+ */
+@RestController
+@RequestMapping("${hsweb.web.mappings.file-info:file-info}")
+@Authorize(permission = "file-info")
+@AccessLogger("文件信息")
+public class FileInfoController implements SimpleGenericEntityController<FileInfoEntity, String, QueryParamEntity> {
+
+    private FileInfoService fileInfoService;
+
+    @Autowired
+    public void setFileInfoService(FileInfoService fileInfoService) {
+        this.fileInfoService = fileInfoService;
+    }
+
+    @Override
+    public FileInfoService getService() {
+        return fileInfoService;
+    }
+}

+ 27 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-api/pom.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-file-dao</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file-dao-api</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-entity</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-dao-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 11 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-api/src/main/java/org/hswebframework/web/dao/file/FileInfoDao.java

@@ -0,0 +1,11 @@
+package org.hswebframework.web.dao.file;
+
+import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.entity.file.FileInfoEntity;
+
+/**
+*  文件信息 DAO接口
+*  @author hsweb-generator-online
+ */
+public interface FileInfoDao extends CrudDao<FileInfoEntity,String> {
+}

+ 26 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-mybatis/pom.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-file-dao</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file-dao-mybatis</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-dao-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-dao-mybatis</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 53 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-dao/hsweb-system-file-dao-mybatis/src/main/resources/org/hswebframework/web/dao/mybatis/mappers/file/FileInfoMapper.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.hswebframework.web.dao.file.FileInfoDao">
+    <resultMap id="FileInfoResultMap" type="org.hswebframework.web.entity.file.FileInfoEntity">
+        <id property="id" column="u_id" javaType="string" jdbcType="VARCHAR"/>
+        <result property="name" column="name" javaType="String" jdbcType="VARCHAR"/>
+        <result property="location" column="path" javaType="String" jdbcType="VARCHAR"/>
+        <result property="type" column="type" javaType="String" jdbcType="VARCHAR"/>
+        <result property="md5" column="md5" javaType="String" jdbcType="VARCHAR"/>
+        <result property="size" column="size" javaType="Long" jdbcType="DECIMAL"/>
+        <result property="status" column="status" javaType="Long" jdbcType="DECIMAL"/>
+        <result property="classified" column="classified" javaType="String" jdbcType="VARCHAR"/>
+        <result property="createTime" column="create_time" javaType="Long" jdbcType="NUMERIC"/>
+        <result property="creatorId" column="creator_id" javaType="String" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <!--用于动态生成sql所需的配置-->
+    <sql id="config">
+        <bind name="resultMapId" value="'FileInfoResultMap'"/>
+        <bind name="tableName" value="'s_file_info'"/>
+    </sql>
+
+    <insert id="insert" parameterType="org.hswebframework.web.entity.file.FileInfoEntity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildInsertSql"/>
+    </insert>
+
+    <delete id="deleteByPk" parameterType="String">
+        delete from s_file_info where u_id =#{id}
+    </delete>
+
+    <delete id="delete" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildDeleteSql"/>
+    </delete>
+
+    <update id="update" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildUpdateSql"/>
+    </update>
+
+    <select id="query" parameterType="org.hswebframework.web.commons.entity.Entity" resultMap="FileInfoResultMap">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildSelectSql"/>
+    </select>
+
+    <select id="count" parameterType="org.hswebframework.web.commons.entity.Entity" resultType="int">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildTotalSql"/>
+    </select>
+</mapper>

+ 18 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-dao/pom.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-file</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file-dao</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>hsweb-system-file-dao-api</module>
+        <module>hsweb-system-file-dao-mybatis</module>
+    </modules>
+</project>

+ 22 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-entity/pom.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-file</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file-entity</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-entity</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 115 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-entity/src/main/java/org/hswebframework/web/entity/file/FileInfoEntity.java

@@ -0,0 +1,115 @@
+package org.hswebframework.web.entity.file;
+
+import org.hswebframework.web.commons.entity.GenericEntity;
+import org.hswebframework.web.commons.entity.RecordCreationEntity;
+
+/**
+ * 文件信息 实体
+ *
+ * @author hsweb-generator-online
+ */
+public interface FileInfoEntity extends RecordCreationEntity, GenericEntity<String> {
+ /*-------------------------------------------
+    |               属性名常量               |
+    ===========================================*/
+    /**
+     * 文件名称
+     */
+    String name       = "name";
+    /**
+     * 文件相对路径
+     */
+    String location   = "location";
+    /**
+     * 类型
+     */
+    String type       = "type";
+    /**
+     * md5校验值
+     */
+    String md5        = "md5";
+    /**
+     * 文件大小
+     */
+    String size       = "size";
+    /**
+     * 状态
+     */
+    String status     = "status";
+    /**
+     * 分类
+     */
+    String classified = "classified";
+
+    /**
+     * @return 文件名称
+     */
+    String getName();
+
+    /**
+     * @param name 文件名称
+     */
+    void setName(String name);
+
+    /**
+     * @return 路径
+     */
+    String getLocation();
+
+    /**
+     * @param location 文件相对路径
+     */
+    void setLocation(String location);
+
+    /**
+     * @return 类型
+     */
+    String getType();
+
+    /**
+     * @param type 类型
+     */
+    void setType(String type);
+
+    /**
+     * @return md5校验值
+     */
+    String getMd5();
+
+    /**
+     * @param md5 md5校验值
+     */
+    void setMd5(String md5);
+
+    /**
+     * @return 文件大小
+     */
+    Long getSize();
+
+    /**
+     * @param size 文件大小
+     */
+    void setSize(Long size);
+
+    /**
+     * @return 状态
+     */
+    Byte getStatus();
+
+    /**
+     * @param status 状态
+     */
+    void setStatus(Byte status);
+
+    /**
+     * @return 分类
+     */
+    String getClassified();
+
+    /**
+     * @param classified 分类
+     */
+    void setClassified(String classified);
+
+
+}

+ 147 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-entity/src/main/java/org/hswebframework/web/entity/file/SimpleFileInfoEntity.java

@@ -0,0 +1,147 @@
+package org.hswebframework.web.entity.file;
+
+import org.hswebframework.web.commons.entity.SimpleGenericEntity;
+
+/**
+ * 文件信息
+ *
+ * @author hsweb-generator-online
+ */
+public class SimpleFileInfoEntity extends SimpleGenericEntity<String> implements FileInfoEntity {
+    //文件名称
+    private String name;
+    //路径
+    private String location;
+    //类型
+    private String type;
+    //md5校验值
+    private String md5;
+    //文件大小
+    private Long   size;
+    //状态
+    private Byte   status;
+    //分类
+    private String classified;
+    //创建时间
+    private Long   createTime;
+    //创建人
+    private String creatorId;
+
+    /**
+     * @return 文件名称
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * @param name 文件名称
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getLocation() {
+        return location;
+    }
+
+    @Override
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    /**
+     * @return 类型
+     */
+    public String getType() {
+        return this.type;
+    }
+
+    /**
+     * @param type 类型
+     */
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    /**
+     * @return md5校验值
+     */
+    public String getMd5() {
+        return this.md5;
+    }
+
+    /**
+     * @param md5 md5校验值
+     */
+    public void setMd5(String md5) {
+        this.md5 = md5;
+    }
+
+    /**
+     * @return 文件大小
+     */
+    public Long getSize() {
+        return this.size;
+    }
+
+    /**
+     * @param size 文件大小
+     */
+    public void setSize(Long size) {
+        this.size = size;
+    }
+
+    /**
+     * @return 状态
+     */
+    public Byte getStatus() {
+        return this.status;
+    }
+
+    /**
+     * @param status 状态
+     */
+    public void setStatus(Byte status) {
+        this.status = status;
+    }
+
+    /**
+     * @return 分类
+     */
+    public String getClassified() {
+        return this.classified;
+    }
+
+    /**
+     * @param classified 分类
+     */
+    public void setClassified(String classified) {
+        this.classified = classified;
+    }
+
+    /**
+     * @return 创建人
+     */
+    public String getCreatorId() {
+        return this.creatorId;
+    }
+
+    @Override
+    public Long getCreateTime() {
+        return createTime;
+    }
+
+    @Override
+    public void setCreateTime(Long createTime) {
+        this.createTime = createTime;
+    }
+
+    /**
+     * @param creatorId 创建人
+     */
+    public void setCreatorId(String creatorId) {
+        this.creatorId = creatorId;
+    }
+}

+ 12 - 1
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/pom.xml

@@ -11,5 +11,16 @@
 
     <artifactId>hsweb-system-file-service-api</artifactId>
 
-
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-commons-service-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-dao-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
 </project>

+ 0 - 27
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/src/main/java/org/hswebframework/web/service/file/FileInfo.java

@@ -1,27 +0,0 @@
-package org.hswebframework.web.service.file;
-
-import java.io.Serializable;
-
-/**
- * Created by zhouhao on 2017/7/8.
- */
-public interface FileInfo  extends Serializable{
-
-    String getId();
-
-    void setId(String id);
-
-    String getName();
-
-    long getLength();
-
-    long getCreateTime();
-
-    String getCreatorId();
-
-    String getMd5();
-
-    String getLocation();
-
-
-}

+ 13 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/src/main/java/org/hswebframework/web/service/file/FileInfoService.java

@@ -0,0 +1,13 @@
+package org.hswebframework.web.service.file;
+
+import org.hswebframework.web.entity.file.FileInfoEntity;
+import org.hswebframework.web.service.CrudService;
+
+/**
+ * 文件信息 服务类
+ *
+ * @author hsweb-generator-online
+ */
+public interface FileInfoService extends CrudService<FileInfoEntity, String> {
+    FileInfoEntity selectByMd5(String md5);
+}

+ 42 - 3
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-api/src/main/java/org/hswebframework/web/service/file/FileService.java

@@ -1,19 +1,58 @@
 package org.hswebframework.web.service.file;
 
+import org.hswebframework.web.entity.file.FileInfoEntity;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
 /**
+ * 文件服务,用户保存,读取文件信息
+ *
+ * @author zhouhao
+ * @since 3.0
  */
 public interface FileService {
 
+    /**
+     * 根据文件id获取文件流,如果文件不存在,将抛出{@link org.hswebframework.web.NotFoundException}
+     *
+     * @param fileId 文件id
+     * @return 文件流
+     */
     InputStream readFile(String fileId);
 
-    FileInfo saveFile(InputStream fileStream,String fileName,String creatorId) throws IOException;
+    /**
+     * 保存文件,并返回文件信息,如果存在相同的文件,则不会保存,而是返回已保存的文件
+     *
+     * @param fileStream 文件输入流
+     * @param fileName   文件名称
+     * @param type       文件类型(contentType)
+     * @param creatorId  上传人
+     * @return 文件信息
+     * @throws IOException
+     * @see FileInfoEntity
+     */
+    FileInfoEntity saveFile(InputStream fileStream, String fileName, String type, String creatorId) throws IOException;
 
-    void writeFile(String fileId, OutputStream out);
+    /**
+     * 上传静态文件,并返回静态文件访问地址
+     *
+     * @param fileStream 文件输入流
+     * @param fileName   文件名
+     * @return 上传文件的访问地址
+     * @throws IOException
+     */
+    String saveStaticFile(InputStream fileStream, String fileName) throws IOException;
 
-    String md5(String fileId);
+    /**
+     * 将已上传的文件写出到指定的输出流
+     *
+     * @param fileId 已上传的文件id
+     * @param out    要写出的流
+     * @param skip   跳过写出 {@link InputStream#skip(long)}
+     * @throws IOException
+     */
+    void writeFile(String fileId, OutputStream out, long skip) throws IOException;
 
 }

+ 4 - 9
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/pom.xml

@@ -11,21 +11,16 @@
 
     <artifactId>hsweb-system-file-service-simple</artifactId>
 
-
     <dependencies>
         <dependency>
             <groupId>org.hswebframework.web</groupId>
-            <artifactId>hsweb-system-file-service-api</artifactId>
+            <artifactId>hsweb-commons-service-simple</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.hswebframework</groupId>
-            <artifactId>hsweb-utils</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-service-api</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 </project>

+ 126 - 25
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/src/main/java/org/hswebframework/web/service/file/LocalFileService.java

@@ -2,34 +2,121 @@ package org.hswebframework.web.service.file;
 
 import org.apache.commons.codec.digest.DigestUtils;
 import org.hswebframework.utils.time.DateFormatter;
+import org.hswebframework.web.NotFoundException;
+import org.hswebframework.web.commons.entity.DataStatus;
+import org.hswebframework.web.entity.file.FileInfoEntity;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.StreamUtils;
 
 import java.io.*;
 import java.util.Date;
 
 /**
- * Created by zhouhao on 2017/7/8.
+ * 本地文件服务,将文件上传到本地文件系统中
+ *
+ * @author zhouhao
+ * @since 3.0
  */
 public class LocalFileService implements FileService {
+    private FileInfoService fileInfoService;
 
-    private String fileBasePath=".";
+    /**
+     * 静态文件存储目录,不能以/结尾
+     */
+    private String staticFilePath = "./static";
 
+    /**
+     * 静态文件访问地址,上传静态文件后,将返回此地址+文件相对地址,以/结尾
+     */
+    private String staticLocation = "/";
 
-    public String getFileBasePath() {
-        return fileBasePath;
+    /**
+     * 文件上传目录
+     */
+    private String filePath = "./upload";
+
+    @Value("${hsweb.web.upload.staticFilePath:./static}")
+    public void setStaticFilePath(String staticFilePath) {
+        this.staticFilePath = staticFilePath;
+    }
+
+    @Value("${hsweb.web.upload.staticLocation:/}")
+    public void setStaticLocation(String staticLocation) {
+        this.staticLocation = staticLocation;
+    }
+
+    @Value("${hsweb.web.upload.filePath:./upload}")
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public String getStaticFilePath() {
+        return staticFilePath;
+    }
+
+    public String getStaticLocation() {
+        return staticLocation;
+    }
+
+    @Autowired
+    public void setFileInfoService(FileInfoService fileInfoService) {
+        this.fileInfoService = fileInfoService;
     }
 
     @Override
     public InputStream readFile(String fileId) {
+        FileInfoEntity fileInfo = fileInfoService.selectByMd5(fileId);
+        if (fileInfo == null || DataStatus.STATUS_ENABLED.equals(fileInfo.getStatus())) {
+            throw new NotFoundException("file not found or disabled");
+        }
+        //配置中的文件上传根路径
+        String filePath = fileInfo.getLocation();
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new NotFoundException("file not found");
+        }
+        try {
+            return new FileInputStream(file);
+        } catch (FileNotFoundException ignore) {
+            //  never happen
+            throw new NotFoundException("file not found");
+        }
+    }
+
+    @Override
+    public String saveStaticFile(InputStream fileStream, String fileName) throws IOException {
+        //文件后缀
+        String suffix = fileName.contains(".") ?
+                fileName.substring(fileName.lastIndexOf("."), fileName.length()) : "";
+
+        //以日期划分目录
+        String filePath = DateFormatter.toString(new Date(), "yyyyMMdd");
+
+        //创建目录
+        new File(filePath).mkdirs();
+
+        // 存储的文件名
+        String realFileName = System.nanoTime() + suffix;
 
-        return null;
+        String fileAbsName = getStaticFilePath() + "/" + filePath + "/" + realFileName;
+        try (FileOutputStream out = new FileOutputStream(fileAbsName)) {
+            StreamUtils.copy(fileStream, out);
+        }
+        //响应上传成功的资源信息
+        return getStaticLocation() + filePath + "/" + realFileName;
     }
 
     @Override
-    public FileInfo saveFile(InputStream fileStream, String fileName,String creatorId) throws IOException {
+    public FileInfoEntity saveFile(InputStream fileStream, String fileName, String type, String creatorId) throws IOException {
         //配置中的文件上传根路径
-        String fileBasePath = getFileBasePath();
+        String fileBasePath = getFilePath();
         //文件存储的相对路径,以日期分隔,每天创建一个新的目录
-        String filePath = "/file/".concat(DateFormatter.toString(new Date(),"yyyy-MM-dd"));
+        String filePath = "/file/".concat(DateFormatter.toString(new Date(), "yyyyMMdd"));
         //文件存储绝对路径
         String absPath = fileBasePath.concat(filePath);
         File path = new File(absPath);
@@ -43,7 +130,7 @@ public class LocalFileService implements FileService {
             byte[] buffer = new byte[2048 * 10];
             int len;
             while ((len = in.read(buffer)) != -1) {
-                fileLength+=len;
+                fileLength += len;
                 os.write(buffer, 0, len);
             }
             os.flush();
@@ -54,25 +141,39 @@ public class LocalFileService implements FileService {
         try (FileInputStream inputStream = new FileInputStream(newFile)) {
             md5 = DigestUtils.md5Hex(inputStream);
         }
-        //判断文件是否已经存在
-      //  Resources resources = resourcesService.selectByMd5(md5);
-       // if (resources != null) {
-         //   newFile.delete();//文件已存在则删除临时文件不做处理
-           // return resources;
-        //} else {
-          //  newName = md5;
-            //newFile.renameTo(new File(absPath.concat("/").concat(newName)));
-        //}
-        return null;
+        //  判断文件是否已经存在
+        FileInfoEntity resources = fileInfoService.selectByMd5(md5);
+        if (resources != null) {
+            newFile.delete();//文件已存在则删除临时文件不做处理
+            return resources;
+        } else {
+            newName = md5;
+            newFile.renameTo(new File(absPath.concat("/").concat(newName)));
+        }
+        FileInfoEntity infoEntity = fileInfoService.createEntity();
+        infoEntity.setCreateTimeNow();
+        infoEntity.setCreatorId(creatorId);
+        infoEntity.setLocation(filePath.concat("/").concat(md5));
+        infoEntity.setName(fileName);
+        infoEntity.setType(type);
+        infoEntity.setSize(fileLength);
+        infoEntity.setMd5(md5);
+        infoEntity.setStatus(DataStatus.STATUS_ENABLED);
+        fileInfoService.insert(infoEntity);
+        return infoEntity;
     }
 
     @Override
-    public void writeFile(String fileId, OutputStream out) {
-
+    public void writeFile(String fileId, OutputStream out, long skip) throws IOException {
+        try (InputStream inputStream = readFile(fileId)) {
+            BufferedOutputStream outputStream = out instanceof BufferedOutputStream ? ((BufferedOutputStream) out) : new BufferedOutputStream(out);
+            if (skip > 0) inputStream.skip(skip);
+            byte b[] = new byte[2048 * 10];
+            while ((inputStream.read(b)) != -1) {
+                outputStream.write(b);
+            }
+            outputStream.flush();
+        }
     }
 
-    @Override
-    public String md5(String fileId) {
-        return null;
-    }
 }

+ 79 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-service/hsweb-system-file-service-simple/src/main/java/org/hswebframework/web/service/file/simple/SimpleFileInfoService.java

@@ -0,0 +1,79 @@
+package org.hswebframework.web.service.file.simple;
+
+import org.hswebframework.web.dao.file.FileInfoDao;
+import org.hswebframework.web.entity.file.FileInfoEntity;
+import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.service.GenericEntityService;
+import org.hswebframework.web.service.file.FileInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cache.annotation.Caching;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 默认的服务实现
+ *
+ * @author hsweb-generator-online
+ */
+@Service("fileInfoService")
+@CacheConfig(cacheNames = "file-info")
+public class SimpleFileInfoService extends GenericEntityService<FileInfoEntity, String>
+        implements FileInfoService {
+    private FileInfoDao fileInfoDao;
+
+    @Override
+    protected IDGenerator<String> getIDGenerator() {
+        return IDGenerator.MD5;
+    }
+
+    @Override
+    public FileInfoDao getDao() {
+        return fileInfoDao;
+    }
+
+    @Autowired
+    public void setFileInfoDao(FileInfoDao fileInfoDao) {
+        this.fileInfoDao = fileInfoDao;
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'md5:'+#entity.md5"),
+            @CacheEvict(key = "'id:'+#entity.id")
+    })
+    protected int updateByPk(FileInfoEntity entity) {
+        return super.updateByPk(entity);
+    }
+
+    @Override
+    @Caching(evict = {
+            @CacheEvict(key = "'md5:'+#target.selectByPk(#id).md5"),
+            @CacheEvict(key = "'id:'+#id")
+    })
+    public int deleteByPk(String id) {
+        return super.deleteByPk(id);
+    }
+
+    @Override
+    @CacheEvict(allEntries = true)
+    public int updateByPk(List<FileInfoEntity> data) {
+        return super.updateByPk(data);
+    }
+
+    @Override
+    @Cacheable(key = "'id:'+#id", condition = "#id!=null")
+    public FileInfoEntity selectByPk(String id) {
+        return super.selectByPk(id);
+    }
+
+    @Override
+    @Cacheable(key = "'md5:'+#md5", condition = "#md5!=null")
+    public FileInfoEntity selectByMd5(String md5) {
+        if (null == md5) return null;
+        return createQuery().where(FileInfoEntity.md5, md5).single();
+    }
+}

+ 78 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-starter/pom.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system-file</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file-starter</artifactId>
+
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-service-simple</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+      
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-dao-mybatis</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+      
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-file-controller</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+      
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.0.26</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-spring-boot-starter</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-tests</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>test</scope>
+        </dependency>
+      
+    </dependencies>
+</project>

+ 48 - 0
hsweb-system/hsweb-system-file/hsweb-system-file-starter/src/main/resources/hsweb-starter.js

@@ -0,0 +1,48 @@
+//组件信息
+var info = {
+    groupId: "${project.groupId}",
+    artifactId: "${project.artifactId}",
+    version: "${project.version}",
+    website: "https://github.com/hs-web/hsweb-framework",
+    author: "admin@hsweb.me",
+    comment: "文件信息"
+};
+
+//版本更新信息
+var versions = [
+    // {
+    //     version: "3.0.2",
+    //     upgrade: function (context) {
+    //         java.lang.System.out.println("更新到3.0.2了");
+    //     }
+    // }
+];
+var JDBCType = java.sql.JDBCType;
+function install(context) {
+    var database = context.database;
+    database.createOrAlter("s_file_info")
+        .addColumn().name("u_id").alias("id").comment("ID").jdbcType(java.sql.JDBCType.VARCHAR).length(32).primaryKey().commit()
+        .addColumn().name("name").alias("name").comment("文件名称").jdbcType(java.sql.JDBCType.VARCHAR).length(256).commit()
+        .addColumn().name("location").alias("location").comment("文件相对路径").jdbcType(java.sql.JDBCType.VARCHAR).length(1024).commit()
+        .addColumn().name("type").alias("type").comment("类型").jdbcType(java.sql.JDBCType.VARCHAR).length(256).commit()
+        .addColumn().name("md5").alias("md5").comment("md5校验值").jdbcType(java.sql.JDBCType.VARCHAR).length(256).commit()
+        .addColumn().name("size").alias("size").comment("文件大小").jdbcType(java.sql.JDBCType.DECIMAL).length(32, 0).commit()
+        .addColumn().name("status").alias("status").comment("状态").jdbcType(java.sql.JDBCType.DECIMAL).length(4, 0).commit()
+        .addColumn().name("classified").alias("classified").comment("分类").jdbcType(java.sql.JDBCType.VARCHAR).length(32).commit()
+        .addColumn().name("create_time").alias("create_time").comment("创建时间").jdbcType(java.sql.JDBCType.NUMERIC).length(32).commit()
+        .addColumn().name("creator_id").alias("creatorId").comment("创建人").jdbcType(java.sql.JDBCType.VARCHAR).length(256).commit()
+        .comment("文件信息").commit();
+}
+//设置依赖
+dependency.setup(info)
+    .onInstall(install)
+    .onUpgrade(function (context) { //更新时执行
+        var upgrader = context.upgrader;
+        upgrader.filter(versions)
+            .upgrade(function (newVer) {
+                newVer.upgrade(context);
+            });
+    })
+    .onUninstall(function (context) { //卸载时执行
+
+    });

+ 4 - 0
hsweb-system/hsweb-system-file/pom.xml

@@ -13,6 +13,10 @@
     <packaging>pom</packaging>
     <modules>
         <module>hsweb-system-file-service</module>
+        <module>hsweb-system-file-controller</module>
+        <module>hsweb-system-file-dao</module>
+        <module>hsweb-system-file-entity</module>
+        <module>hsweb-system-file-starter</module>
     </modules>