完善文件V2功能,修改文件下载方式为重定向下载,增加查看码校验,增加文件下载次数统计
This commit is contained in:
parent
5c8ed3e294
commit
56b317684d
@ -0,0 +1,31 @@
|
|||||||
|
package ink.wgink.module.file.config;
|
||||||
|
|
||||||
|
import ink.wgink.module.file.filter.FilesFilter;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileConfig
|
||||||
|
* @Description: 文件配置
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/1 09:48
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class FileConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean filesFilter() {
|
||||||
|
FilesFilter filesFilter = new FilesFilter();
|
||||||
|
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
|
||||||
|
filterRegistrationBean.setFilter(filesFilter);
|
||||||
|
filterRegistrationBean.addUrlPatterns("/files/*");
|
||||||
|
filterRegistrationBean.setName("filesFilter");
|
||||||
|
filterRegistrationBean.setOrder(20);
|
||||||
|
return filterRegistrationBean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package ink.wgink.module.file.controller.api.filedownload;
|
||||||
|
|
||||||
|
import ink.wgink.common.base.DefaultBaseController;
|
||||||
|
import ink.wgink.interfaces.consts.ISystemConstant;
|
||||||
|
import ink.wgink.module.file.pojo.dtos.filedownload.FileDownloadDTO;
|
||||||
|
import ink.wgink.module.file.service.filedownload.IFileDownloadService;
|
||||||
|
import ink.wgink.pojo.ListPage;
|
||||||
|
import ink.wgink.pojo.result.ErrorResult;
|
||||||
|
import ink.wgink.pojo.result.SuccessResultList;
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileDownloadController
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 16:21
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件下载接口")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(ISystemConstant.API_PREFIX + "/file-download")
|
||||||
|
public class FileDownloadController extends DefaultBaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IFileDownloadService fileDownloadService;
|
||||||
|
|
||||||
|
@ApiOperation(value = "下载分页列表", notes = "下载分页列表接口")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", defaultValue = "1"),
|
||||||
|
@ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "int", defaultValue = "20"),
|
||||||
|
})
|
||||||
|
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
|
||||||
|
@GetMapping("listpage/file-id/{fileId}")
|
||||||
|
public SuccessResultList<List<FileDownloadDTO>> listPageByFileId(@PathVariable("fileId") String fileId, ListPage page) {
|
||||||
|
Map<String, Object> params = requestParams();
|
||||||
|
page.setParams(params);
|
||||||
|
return fileDownloadService.listPageByFileId(fileId, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,18 +3,23 @@ package ink.wgink.module.file.controller.api.v2;
|
|||||||
import ink.wgink.common.base.DefaultBaseController;
|
import ink.wgink.common.base.DefaultBaseController;
|
||||||
import ink.wgink.interfaces.consts.ISystemConstant;
|
import ink.wgink.interfaces.consts.ISystemConstant;
|
||||||
import ink.wgink.module.file.enums.UploadTypeEnum;
|
import ink.wgink.module.file.enums.UploadTypeEnum;
|
||||||
|
import ink.wgink.module.file.pojo.dtos.FileInfoDTO;
|
||||||
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
|
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
|
||||||
import ink.wgink.module.file.service.v2.IFileService;
|
import ink.wgink.module.file.service.v2.IFileService;
|
||||||
|
import ink.wgink.pojo.ListPage;
|
||||||
import ink.wgink.pojo.result.ErrorResult;
|
import ink.wgink.pojo.result.ErrorResult;
|
||||||
|
import ink.wgink.pojo.result.SuccessResult;
|
||||||
import ink.wgink.pojo.result.SuccessResultData;
|
import ink.wgink.pojo.result.SuccessResultData;
|
||||||
|
import ink.wgink.pojo.result.SuccessResultList;
|
||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.*;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ClassName: FileController
|
* @ClassName: FileController
|
||||||
* @Description: 文件处理
|
* @Description: 文件处理
|
||||||
@ -22,7 +27,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
* @Date: 2019/3/10 7:03 PM
|
* @Date: 2019/3/10 7:03 PM
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
**/
|
**/
|
||||||
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件接口")
|
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件接口-V2")
|
||||||
@RestController("fileControllerV2")
|
@RestController("fileControllerV2")
|
||||||
@RequestMapping(ISystemConstant.API_PREFIX + "/file/v2")
|
@RequestMapping(ISystemConstant.API_PREFIX + "/file/v2")
|
||||||
public class FileController extends DefaultBaseController {
|
public class FileController extends DefaultBaseController {
|
||||||
@ -70,11 +75,35 @@ public class FileController extends DefaultBaseController {
|
|||||||
return uploadSingle(audio, UploadTypeEnum.AUDIO);
|
return uploadSingle(audio, UploadTypeEnum.AUDIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "删除文件", notes = "删除文件接口")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "ids", value = "ID列表,用下划线分隔", paramType = "path", example = "1_2_3")
|
||||||
|
})
|
||||||
|
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
|
||||||
|
@DeleteMapping("delete/{ids}")
|
||||||
|
public synchronized SuccessResult delete(@PathVariable("ids") String ids) {
|
||||||
|
fileService.delete(Arrays.asList(ids.split("\\_")));
|
||||||
|
return new SuccessResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "文件分页列表", notes = "文件分页列表接口")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", defaultValue = "1"),
|
||||||
|
@ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "int", defaultValue = "20"),
|
||||||
|
@ApiImplicitParam(name = "keywords", value = "关键字", paramType = "query", dataType = "String")
|
||||||
|
})
|
||||||
|
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
|
||||||
|
@GetMapping("listpage")
|
||||||
|
public SuccessResultList<List<FileInfoDTO>> listPage(ListPage page) {
|
||||||
|
Map<String, Object> params = requestParams();
|
||||||
|
page.setParams(params);
|
||||||
|
return fileService.listPage(page);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传文件
|
* 上传文件
|
||||||
*
|
*
|
||||||
* @param uploadFile
|
* @param uploadFile
|
||||||
* @param params
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private SuccessResultData<FileUploadSuccessDTO> uploadSingle(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
|
private SuccessResultData<FileUploadSuccessDTO> uploadSingle(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package ink.wgink.module.file.controller.route.filedownload;
|
||||||
|
|
||||||
|
import ink.wgink.interfaces.consts.ISystemConstant;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileDownloadRouteController
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 16:34
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件下载")
|
||||||
|
@Controller
|
||||||
|
@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/file-download")
|
||||||
|
public class FileDownloadRouteController {
|
||||||
|
|
||||||
|
@GetMapping("list")
|
||||||
|
public ModelAndView list() {
|
||||||
|
ModelAndView modelAndView = new ModelAndView("file-download/list");
|
||||||
|
return modelAndView;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package ink.wgink.module.file.controller.route.v2;
|
||||||
|
|
||||||
|
import ink.wgink.interfaces.consts.ISystemConstant;
|
||||||
|
import ink.wgink.module.file.service.v2.IFileService;
|
||||||
|
import ink.wgink.pojo.result.ErrorResult;
|
||||||
|
import io.swagger.annotations.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileRouteController
|
||||||
|
* @Description: 文件路由
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/1 15:21
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件路由-V2")
|
||||||
|
@Controller("fileRouteControllerV2")
|
||||||
|
@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/file/v2")
|
||||||
|
public class FileRouteController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IFileService fileService;
|
||||||
|
|
||||||
|
@GetMapping("list")
|
||||||
|
public ModelAndView list() {
|
||||||
|
ModelAndView modelAndView = new ModelAndView("file/v2/list");
|
||||||
|
return modelAndView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "文件下载", notes = "文件下载接口")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "isOpen", value = "是否打开,true和false", paramType = "path"),
|
||||||
|
@ApiImplicitParam(name = "fileId", value = "文件ID", paramType = "path")
|
||||||
|
})
|
||||||
|
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
|
||||||
|
@GetMapping("download/{isOpen}/{fileId}")
|
||||||
|
public void download(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
@PathVariable("isOpen") Boolean isOpen,
|
||||||
|
@PathVariable("fileId") String fileId) {
|
||||||
|
fileService.download(request, response, isOpen, fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package ink.wgink.module.file.dao.filedownload;
|
||||||
|
|
||||||
|
import ink.wgink.exceptions.SaveException;
|
||||||
|
import ink.wgink.exceptions.SearchException;
|
||||||
|
import ink.wgink.interfaces.init.IInitBaseTable;
|
||||||
|
import ink.wgink.module.file.pojo.dtos.filedownload.FileDownloadDTO;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: IFileDownloadDao
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 09:58
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IFileDownloadDao extends IInitBaseTable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增下载记录
|
||||||
|
*
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
void save(Map<String, Object> params) throws SaveException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载记录列表
|
||||||
|
*
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
* @throws SearchException
|
||||||
|
*/
|
||||||
|
List<FileDownloadDTO> list(Map<String, Object> params) throws SearchException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载记录统计
|
||||||
|
*
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
* @throws SearchException
|
||||||
|
*/
|
||||||
|
Integer count(Map<String, Object> params) throws SearchException;
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package ink.wgink.module.file.filter;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import ink.wgink.exceptions.base.SystemException;
|
||||||
|
import ink.wgink.module.file.manager.FilesManager;
|
||||||
|
import ink.wgink.pojo.bos.files.FilesShowCode;
|
||||||
|
import ink.wgink.pojo.result.ErrorResult;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FilesFilter
|
||||||
|
* @Description: 文件过滤器
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/1 09:21
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class FilesFilter implements Filter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
Filter.super.init(filterConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||||
|
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||||
|
String fileId = request.getParameter("file");
|
||||||
|
String code = request.getParameter("code");
|
||||||
|
String isOpen = request.getParameter("open");
|
||||||
|
if (StringUtils.isBlank(code)) {
|
||||||
|
notFoundResponse(response, "查看码不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(fileId)) {
|
||||||
|
notFoundResponse(response, "文件不存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FilesShowCode showCode = FilesManager.getInstance().getShowCode(fileId, code);
|
||||||
|
if (Integer.parseInt(isOpen) == 0) {
|
||||||
|
// 下载
|
||||||
|
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(showCode.getFileName(), "UTF-8"));
|
||||||
|
}
|
||||||
|
} catch (SystemException e) {
|
||||||
|
notFoundResponse(response, e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
Filter.super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件未找到
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* @param errorInfo
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void notFoundResponse(HttpServletResponse response, String errorInfo) throws IOException {
|
||||||
|
response.setStatus(HttpStatus.NOT_FOUND.value());
|
||||||
|
response.setHeader("Content-Type", "application/json;charset=UTF-8");
|
||||||
|
ErrorResult result = new ErrorResult(ErrorResult.ErrorResultCodeEnum.FILE_ERROR.getValue(), errorInfo);
|
||||||
|
response.getWriter().write(JSON.toJSONString(result));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package ink.wgink.module.file.impl;
|
||||||
|
|
||||||
|
import ink.wgink.exceptions.ParamsException;
|
||||||
|
import ink.wgink.interfaces.manager.IFilesShowCodeService;
|
||||||
|
import ink.wgink.pojo.bos.files.FilesShowCode;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileShowCodeServiceImpl
|
||||||
|
* @Description: 文件显示码
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/1 17:16
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DefaultFilesShowCodeServiceImpl implements IFilesShowCodeService {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(DefaultFilesShowCodeServiceImpl.class);
|
||||||
|
private Map<String, FilesShowCode> showCodeMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addShowCode(String code, String fileId, String fileName) {
|
||||||
|
showCodeMap.put(fileId, new FilesShowCode(code, fileId, fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearTimeoutShowCode() {
|
||||||
|
Set<String> keySet = showCodeMap.keySet();
|
||||||
|
long currentTimeMillis = System.currentTimeMillis();
|
||||||
|
long clearTimeoutShowCodeCount = 0;
|
||||||
|
for (String key : keySet) {
|
||||||
|
FilesShowCode showCode = getShowCode(key);
|
||||||
|
if (currentTimeMillis - showCode.getLatestUpdateTime() > SHOW_CODE_TIMEOUT_MILLIS) {
|
||||||
|
showCodeMap.remove(key);
|
||||||
|
clearTimeoutShowCodeCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.trace(">>>>>> count of clear timeout show code: {}", clearTimeoutShowCodeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FilesShowCode getShowCode(String fileId, String code) {
|
||||||
|
FilesShowCode showCode = getShowCode(fileId);
|
||||||
|
if (showCode == null) {
|
||||||
|
throw new ParamsException("查看码不存在");
|
||||||
|
}
|
||||||
|
if (!StringUtils.equals(showCode.getCode(), code)) {
|
||||||
|
throw new ParamsException("查看码不匹配");
|
||||||
|
}
|
||||||
|
return showCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized FilesShowCode getShowCode(String fileId) {
|
||||||
|
FilesShowCode showCode = showCodeMap.get(fileId);
|
||||||
|
if (showCode != null) {
|
||||||
|
showCode.setLatestUpdateTime(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
return showCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package ink.wgink.module.file.init.build;
|
||||||
|
|
||||||
|
import ink.wgink.interfaces.init.build.IBuildServiceMenu;
|
||||||
|
import ink.wgink.pojo.bos.menu.InitMenuBO;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: BuildFileMenu
|
||||||
|
* @Description: 构建文件菜单
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 17:17
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BuildFileMenu implements IBuildServiceMenu {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildMenu(List<InitMenuBO> initMenus) {
|
||||||
|
InitMenuBO fileParentMenu = new InitMenuBO();
|
||||||
|
fileParentMenu.setMenuName("文件管理");
|
||||||
|
fileParentMenu.setMenuSummary("文件管理");
|
||||||
|
|
||||||
|
// 获取子菜单
|
||||||
|
List<InitMenuBO> subMenus = new ArrayList<>();
|
||||||
|
InitMenuBO initMenu = new InitMenuBO();
|
||||||
|
initMenu.setMenuName("上传文件");
|
||||||
|
initMenu.setMenuSummary("上传文件");
|
||||||
|
initMenu.setMenuUrl("/route/file/v2/list");
|
||||||
|
subMenus.add(initMenu);
|
||||||
|
|
||||||
|
// 设置子菜单
|
||||||
|
fileParentMenu.setSubMenus(subMenus);
|
||||||
|
// 更新子菜单
|
||||||
|
initMenus.add(fileParentMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package ink.wgink.module.file.manager;
|
||||||
|
|
||||||
|
import ink.wgink.interfaces.manager.IFilesShowCodeService;
|
||||||
|
import ink.wgink.pojo.bos.files.FilesShowCode;
|
||||||
|
import ink.wgink.util.string.WStringUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FilesManager
|
||||||
|
* @Description: 文件管理
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/1 10:47
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class FilesManager {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(FilesManager.class);
|
||||||
|
// 查看码超时清理时间,1分钟
|
||||||
|
private static FilesManager filesManager = FilesManagerBuilder.filesManager;
|
||||||
|
private IFilesShowCodeService filesShowCodeService;
|
||||||
|
|
||||||
|
private FilesManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FilesManager getInstance() {
|
||||||
|
return filesManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成显示码
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String generateCode(String fileId, String fileName) {
|
||||||
|
FilesShowCode showCode = filesShowCodeService.getShowCode(fileId);
|
||||||
|
String code;
|
||||||
|
if (showCode == null) {
|
||||||
|
code = WStringUtil.randomSubStr(fileId.replaceAll("-", ""), 4);
|
||||||
|
filesShowCodeService.addShowCode(code, fileId, fileName);
|
||||||
|
} else {
|
||||||
|
code = showCode.getCode();
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除超时显示码
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void clearTimeoutShowCode() {
|
||||||
|
filesShowCodeService.clearTimeoutShowCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取显示码
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
* @param code
|
||||||
|
*/
|
||||||
|
public FilesShowCode getShowCode(String fileId, String code) {
|
||||||
|
return filesShowCodeService.getShowCode(fileId, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilesShowCodeService(IFilesShowCodeService filesShowCodeService) {
|
||||||
|
this.filesShowCodeService = filesShowCodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FilesManagerBuilder {
|
||||||
|
public static FilesManager filesManager = new FilesManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,6 +24,12 @@ public class FileInfoDTO extends FileDTO {
|
|||||||
private String fileSummary;
|
private String fileSummary;
|
||||||
@ApiModelProperty(name = "isBack", value = "是否备份")
|
@ApiModelProperty(name = "isBack", value = "是否备份")
|
||||||
private Integer isBack;
|
private Integer isBack;
|
||||||
|
@ApiModelProperty(name = "creator", value = "创建人")
|
||||||
|
private String creator;
|
||||||
|
@ApiModelProperty(name = "gmtCreate", value = "创建时间")
|
||||||
|
private String gmtCreate;
|
||||||
|
@ApiModelProperty(name = "downloadCount", value = "下载次数")
|
||||||
|
private Integer downloadCount;
|
||||||
|
|
||||||
public String getFilePath() {
|
public String getFilePath() {
|
||||||
return filePath == null ? "" : filePath.trim();
|
return filePath == null ? "" : filePath.trim();
|
||||||
@ -59,6 +65,30 @@ public class FileInfoDTO extends FileDTO {
|
|||||||
this.isBack = isBack;
|
this.isBack = isBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCreator() {
|
||||||
|
return creator == null ? "" : creator.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(String creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGmtCreate() {
|
||||||
|
return gmtCreate == null ? "" : gmtCreate.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGmtCreate(String gmtCreate) {
|
||||||
|
this.gmtCreate = gmtCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDownloadCount() {
|
||||||
|
return downloadCount == null ? 0 : downloadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDownloadCount(Integer downloadCount) {
|
||||||
|
this.downloadCount = downloadCount;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder sb = new StringBuilder("{");
|
final StringBuilder sb = new StringBuilder("{");
|
||||||
@ -70,6 +100,12 @@ public class FileInfoDTO extends FileDTO {
|
|||||||
.append(fileSummary).append('\"');
|
.append(fileSummary).append('\"');
|
||||||
sb.append(",\"isBack\":")
|
sb.append(",\"isBack\":")
|
||||||
.append(isBack);
|
.append(isBack);
|
||||||
|
sb.append(",\"creator\":\"")
|
||||||
|
.append(creator).append('\"');
|
||||||
|
sb.append(",\"gmtCreate\":\"")
|
||||||
|
.append(gmtCreate).append('\"');
|
||||||
|
sb.append(",\"downloadCount\":")
|
||||||
|
.append(downloadCount);
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package ink.wgink.module.file.pojo.dtos.filedownload;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileDownloadDTO
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 10:07
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@ApiModel
|
||||||
|
public class FileDownloadDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "fileDownloadId", value = "主键")
|
||||||
|
private String fileDownloadId;
|
||||||
|
@ApiModelProperty(name = "fileId", value = "文件ID")
|
||||||
|
private String fileId;
|
||||||
|
@ApiModelProperty(name = "clientIp", value = "客户端IP")
|
||||||
|
private String clientIp;
|
||||||
|
@ApiModelProperty(name = "gmtCreate", value = "下载时间")
|
||||||
|
private String gmtCreate;
|
||||||
|
|
||||||
|
public String getFileDownloadId() {
|
||||||
|
return fileDownloadId == null ? "" : fileDownloadId.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileDownloadId(String fileDownloadId) {
|
||||||
|
this.fileDownloadId = fileDownloadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileId() {
|
||||||
|
return fileId == null ? "" : fileId.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileId(String fileId) {
|
||||||
|
this.fileId = fileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientIp() {
|
||||||
|
return clientIp == null ? "" : clientIp.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientIp(String clientIp) {
|
||||||
|
this.clientIp = clientIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGmtCreate() {
|
||||||
|
return gmtCreate == null ? "" : gmtCreate.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGmtCreate(String gmtCreate) {
|
||||||
|
this.gmtCreate = gmtCreate;
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,8 @@ public class FileUploadSuccessDTO implements Serializable {
|
|||||||
private String fileName;
|
private String fileName;
|
||||||
@ApiModelProperty(name = "fileSize", value = "文件大小")
|
@ApiModelProperty(name = "fileSize", value = "文件大小")
|
||||||
private Long fileSize;
|
private Long fileSize;
|
||||||
|
@ApiModelProperty(name = "fileUrl", value = "文件路径")
|
||||||
|
private String fileUrl;
|
||||||
|
|
||||||
public FileUploadSuccessDTO() {
|
public FileUploadSuccessDTO() {
|
||||||
}
|
}
|
||||||
@ -33,6 +35,14 @@ public class FileUploadSuccessDTO implements Serializable {
|
|||||||
this.fileSize = fileSize;
|
this.fileSize = fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FileUploadSuccessDTO(String fileId, String fileName, Long fileSize, String fileUrl) {
|
||||||
|
this.fileId = fileId;
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.fileSize = fileSize;
|
||||||
|
this.fileUrl = fileUrl;
|
||||||
|
}
|
||||||
|
|
||||||
public String getFileId() {
|
public String getFileId() {
|
||||||
return fileId == null ? "" : fileId.trim();
|
return fileId == null ? "" : fileId.trim();
|
||||||
}
|
}
|
||||||
@ -57,6 +67,14 @@ public class FileUploadSuccessDTO implements Serializable {
|
|||||||
this.fileSize = fileSize;
|
this.fileSize = fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFileUrl() {
|
||||||
|
return fileUrl == null ? "" : fileUrl.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileUrl(String fileUrl) {
|
||||||
|
this.fileUrl = fileUrl;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder sb = new StringBuilder("{");
|
final StringBuilder sb = new StringBuilder("{");
|
||||||
@ -66,6 +84,8 @@ public class FileUploadSuccessDTO implements Serializable {
|
|||||||
.append(fileName).append('\"');
|
.append(fileName).append('\"');
|
||||||
sb.append(",\"fileSize\":")
|
sb.append(",\"fileSize\":")
|
||||||
.append(fileSize);
|
.append(fileSize);
|
||||||
|
sb.append(",\"fileUrl\":\"")
|
||||||
|
.append(fileUrl).append('\"');
|
||||||
sb.append('}');
|
sb.append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package ink.wgink.module.file.pojo.vos.filedownload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileDownloadVO
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 09:56
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class FileDownloadVO {
|
||||||
|
|
||||||
|
private String fileId;
|
||||||
|
private String clientIp;
|
||||||
|
|
||||||
|
public FileDownloadVO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDownloadVO(String fileId, String clientIp) {
|
||||||
|
this.fileId = fileId;
|
||||||
|
this.clientIp = clientIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileId() {
|
||||||
|
return fileId == null ? "" : fileId.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileId(String fileId) {
|
||||||
|
this.fileId = fileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientIp() {
|
||||||
|
return clientIp == null ? "" : clientIp.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientIp(String clientIp) {
|
||||||
|
this.clientIp = clientIp;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package ink.wgink.module.file.service.filedownload;
|
||||||
|
|
||||||
|
import ink.wgink.module.file.pojo.dtos.filedownload.FileDownloadDTO;
|
||||||
|
import ink.wgink.module.file.pojo.vos.filedownload.FileDownloadVO;
|
||||||
|
import ink.wgink.pojo.ListPage;
|
||||||
|
import ink.wgink.pojo.result.SuccessResultList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: IFileDownloadService
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 09:58
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public interface IFileDownloadService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增下载记录
|
||||||
|
*
|
||||||
|
* @param fileDownloadVO
|
||||||
|
*/
|
||||||
|
void save(FileDownloadVO fileDownloadVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载列表
|
||||||
|
*
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<FileDownloadDTO> list(Map<String, Object> params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载列表
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<FileDownloadDTO> listByFileId(String fileId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载分页列表
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SuccessResultList<List<FileDownloadDTO>> listPage(ListPage page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载分页列表
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
* @param page
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SuccessResultList<List<FileDownloadDTO>> listPageByFileId(String fileId, ListPage page);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计下载列表
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Integer countByFileId(String fileId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package ink.wgink.module.file.service.filedownload.impl;
|
||||||
|
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import ink.wgink.common.base.DefaultBaseService;
|
||||||
|
import ink.wgink.module.file.dao.filedownload.IFileDownloadDao;
|
||||||
|
import ink.wgink.module.file.pojo.dtos.filedownload.FileDownloadDTO;
|
||||||
|
import ink.wgink.module.file.pojo.vos.filedownload.FileDownloadVO;
|
||||||
|
import ink.wgink.module.file.service.filedownload.IFileDownloadService;
|
||||||
|
import ink.wgink.pojo.ListPage;
|
||||||
|
import ink.wgink.pojo.result.SuccessResultList;
|
||||||
|
import ink.wgink.util.UUIDUtil;
|
||||||
|
import ink.wgink.util.date.DateUtil;
|
||||||
|
import ink.wgink.util.map.HashMapUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileDownloadServiceImpl
|
||||||
|
* @Description: 文件下载
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/2 09:58
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FileDownloadServiceImpl extends DefaultBaseService implements IFileDownloadService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IFileDownloadDao fileDownloadDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(FileDownloadVO fileDownloadVO) {
|
||||||
|
Map<String, Object> params = HashMapUtil.beanToMap(fileDownloadVO);
|
||||||
|
params.put("fileDownloadId", UUIDUtil.getUUID());
|
||||||
|
params.put("gmtCreate", DateUtil.getTime());
|
||||||
|
fileDownloadDao.save(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileDownloadDTO> list(Map<String, Object> params) {
|
||||||
|
params = params == null ? getHashMap(0) : params;
|
||||||
|
return fileDownloadDao.list(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileDownloadDTO> listByFileId(String fileId) {
|
||||||
|
Map<String, Object> params = getHashMap(2);
|
||||||
|
params.put("fileId", fileId);
|
||||||
|
return list(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuccessResultList<List<FileDownloadDTO>> listPage(ListPage page) {
|
||||||
|
PageHelper.startPage(page.getPage(), page.getRows());
|
||||||
|
List<FileDownloadDTO> fileDownloadDTOS = list(page.getParams());
|
||||||
|
PageInfo<FileDownloadDTO> pageInfo = new PageInfo<>(fileDownloadDTOS);
|
||||||
|
return new SuccessResultList<>(fileDownloadDTOS, pageInfo.getPageNum(), pageInfo.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuccessResultList<List<FileDownloadDTO>> listPageByFileId(String fileId, ListPage page) {
|
||||||
|
page.getParams().put("fileId", fileId);
|
||||||
|
return listPage(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer countByFileId(String fileId) {
|
||||||
|
Map<String, Object> params = getHashMap(2);
|
||||||
|
params.put("fileId", fileId);
|
||||||
|
return fileDownloadDao.count(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,13 +1,19 @@
|
|||||||
package ink.wgink.module.file.service.v2;
|
package ink.wgink.module.file.service.v2;
|
||||||
|
|
||||||
import ink.wgink.module.file.enums.UploadTypeEnum;
|
import ink.wgink.module.file.enums.UploadTypeEnum;
|
||||||
|
import ink.wgink.module.file.pojo.dtos.FileInfoDTO;
|
||||||
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
|
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
|
||||||
import ink.wgink.module.file.pojo.vos.v2.FileSaveVO;
|
import ink.wgink.module.file.pojo.vos.v2.FileSaveVO;
|
||||||
import ink.wgink.module.file.pojo.vos.v2.FileUpdateVO;
|
import ink.wgink.module.file.pojo.vos.v2.FileUpdateVO;
|
||||||
|
import ink.wgink.pojo.ListPage;
|
||||||
import ink.wgink.pojo.pos.FilePO;
|
import ink.wgink.pojo.pos.FilePO;
|
||||||
|
import ink.wgink.pojo.result.SuccessResultList;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,6 +102,13 @@ public interface IFileService {
|
|||||||
*/
|
*/
|
||||||
void update(FileUpdateVO fileUpdateVO);
|
void update(FileUpdateVO fileUpdateVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件
|
||||||
|
*
|
||||||
|
* @param fileIds
|
||||||
|
*/
|
||||||
|
void delete(List<String> fileIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件
|
* 获取文件
|
||||||
*
|
*
|
||||||
@ -112,4 +125,30 @@ public interface IFileService {
|
|||||||
*/
|
*/
|
||||||
FilePO getPO(String fileId);
|
FilePO getPO(String fileId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param isOpen 是否打开
|
||||||
|
* @param fileId 文件ID
|
||||||
|
*/
|
||||||
|
void download(HttpServletRequest request, HttpServletResponse response, boolean isOpen, String fileId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件列表
|
||||||
|
*
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<FileInfoDTO> list(Map<String, Object> params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件分页列表
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SuccessResultList<List<FileInfoDTO>> listPage(ListPage page);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,41 @@
|
|||||||
package ink.wgink.module.file.service.v2.impl;
|
package ink.wgink.module.file.service.v2.impl;
|
||||||
|
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
import ink.wgink.common.base.DefaultBaseService;
|
import ink.wgink.common.base.DefaultBaseService;
|
||||||
|
import ink.wgink.exceptions.FileException;
|
||||||
import ink.wgink.exceptions.SearchException;
|
import ink.wgink.exceptions.SearchException;
|
||||||
import ink.wgink.module.file.components.FileComponent;
|
import ink.wgink.module.file.components.FileComponent;
|
||||||
import ink.wgink.module.file.dao.IFileDao;
|
import ink.wgink.module.file.dao.IFileDao;
|
||||||
import ink.wgink.module.file.enums.UploadTypeEnum;
|
import ink.wgink.module.file.enums.UploadTypeEnum;
|
||||||
|
import ink.wgink.module.file.manager.FilesManager;
|
||||||
|
import ink.wgink.module.file.pojo.dtos.FileInfoDTO;
|
||||||
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
|
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
|
||||||
|
import ink.wgink.module.file.pojo.vos.filedownload.FileDownloadVO;
|
||||||
import ink.wgink.module.file.pojo.vos.v2.FileSaveVO;
|
import ink.wgink.module.file.pojo.vos.v2.FileSaveVO;
|
||||||
import ink.wgink.module.file.pojo.vos.v2.FileUpdateVO;
|
import ink.wgink.module.file.pojo.vos.v2.FileUpdateVO;
|
||||||
|
import ink.wgink.module.file.service.filedownload.IFileDownloadService;
|
||||||
import ink.wgink.module.file.service.v2.IFileService;
|
import ink.wgink.module.file.service.v2.IFileService;
|
||||||
|
import ink.wgink.pojo.ListPage;
|
||||||
import ink.wgink.pojo.pos.FilePO;
|
import ink.wgink.pojo.pos.FilePO;
|
||||||
|
import ink.wgink.pojo.result.SuccessResultList;
|
||||||
import ink.wgink.util.UUIDUtil;
|
import ink.wgink.util.UUIDUtil;
|
||||||
import ink.wgink.util.date.DateUtil;
|
import ink.wgink.util.date.DateUtil;
|
||||||
|
import ink.wgink.util.request.RequestUtil;
|
||||||
|
import ink.wgink.util.thread.CachedThreadPoolUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,6 +52,8 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
|
|||||||
private FileComponent fileComponent;
|
private FileComponent fileComponent;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IFileDao fileDao;
|
private IFileDao fileDao;
|
||||||
|
@Autowired
|
||||||
|
private IFileDownloadService fileDownloadService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileUploadSuccessDTO uploadSingle(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
|
public FileUploadSuccessDTO uploadSingle(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
|
||||||
@ -81,12 +100,13 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileUploadSuccessDTO saveFile(FileSaveVO fileSaveVO) {
|
public FileUploadSuccessDTO saveFile(FileSaveVO fileSaveVO) {
|
||||||
|
String fileUrl = fileComponent.getFileUrl(fileSaveVO.getUploadPath());
|
||||||
String fileId = UUIDUtil.getUUID();
|
String fileId = UUIDUtil.getUUID();
|
||||||
Map<String, Object> params = getHashMap(10);
|
Map<String, Object> params = getHashMap(10);
|
||||||
params.put("fileId", fileId);
|
params.put("fileId", fileId);
|
||||||
params.put("fileName", fileSaveVO.getFileName());
|
params.put("fileName", fileSaveVO.getFileName());
|
||||||
params.put("filePath", fileSaveVO.getUploadPath());
|
params.put("filePath", fileSaveVO.getUploadPath());
|
||||||
params.put("fileUrl", fileComponent.getFileUrl(fileSaveVO.getUploadPath()));
|
params.put("fileUrl", fileUrl);
|
||||||
params.put("fileType", fileSaveVO.getFileType());
|
params.put("fileType", fileSaveVO.getFileType());
|
||||||
params.put("fileSize", fileSaveVO.getFileSize());
|
params.put("fileSize", fileSaveVO.getFileSize());
|
||||||
params.put("isBack", 0);
|
params.put("isBack", 0);
|
||||||
@ -99,7 +119,7 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
|
|||||||
params.put("isDelete", 0);
|
params.put("isDelete", 0);
|
||||||
fileDao.save(params);
|
fileDao.save(params);
|
||||||
|
|
||||||
return new FileUploadSuccessDTO(fileId, fileSaveVO.getFileName(), fileSaveVO.getFileSize());
|
return new FileUploadSuccessDTO(fileId, fileSaveVO.getFileName(), fileSaveVO.getFileSize(), fileUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -116,6 +136,26 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
|
|||||||
fileDao.update(params);
|
fileDao.update(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(List<String> fileIds) {
|
||||||
|
if (fileIds.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, Object> params = getHashMap(2);
|
||||||
|
params.put("fileIds", fileIds);
|
||||||
|
List<FilePO> filePOS = fileDao.listPO(params);
|
||||||
|
// 删除源文件
|
||||||
|
filePOS.forEach(filePO -> {
|
||||||
|
File file = new File(filePO.getFilePath());
|
||||||
|
if (!file.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file.delete();
|
||||||
|
});
|
||||||
|
// 删除记录
|
||||||
|
fileDao.delete(params);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FilePO getPO(Map<String, Object> params) {
|
public FilePO getPO(Map<String, Object> params) {
|
||||||
return fileDao.getPO(params);
|
return fileDao.getPO(params);
|
||||||
@ -128,6 +168,87 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
|
|||||||
return getPO(params);
|
return getPO(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void download(HttpServletRequest request, HttpServletResponse response, boolean isOpen, String fileId) {
|
||||||
|
FilePO filePO = getPO(fileId);
|
||||||
|
if (filePO == null) {
|
||||||
|
throw new FileException("查询失败");
|
||||||
|
}
|
||||||
|
File file = new File(filePO.getFilePath());
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new FileException("文件不存在");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String requestIp = RequestUtil.getRequestIp(request);
|
||||||
|
String code = FilesManager.getInstance().generateCode(fileId, filePO.getFileName());
|
||||||
|
response.sendRedirect(String.format("%s/%s?file=%s&code=%s&open=%d", request.getContextPath(), filePO.getFileUrl(), fileId, code, isOpen ? 1 : 0));
|
||||||
|
if (!isOpen && !StringUtils.isBlank(requestIp)) {
|
||||||
|
// 记录下载历史
|
||||||
|
CachedThreadPoolUtil.execute(() -> {
|
||||||
|
FileDownloadVO fileDownloadVO = new FileDownloadVO(filePO.getFileId(), requestIp);
|
||||||
|
fileDownloadService.save(fileDownloadVO);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileInfoDTO> list(Map<String, Object> params) {
|
||||||
|
params = params == null ? getHashMap(0) : params;
|
||||||
|
setQueryFileType(params);
|
||||||
|
List<FileInfoDTO> fileInfoDTOs = fileDao.listInfo(params);
|
||||||
|
setDownloadCount(fileInfoDTOs);
|
||||||
|
return fileInfoDTOs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SuccessResultList<List<FileInfoDTO>> listPage(ListPage page) {
|
||||||
|
PageHelper.startPage(page.getPage(), page.getRows());
|
||||||
|
List<FileInfoDTO> fileInfoDTOs = list(page.getParams());
|
||||||
|
setDownloadCount(fileInfoDTOs);
|
||||||
|
PageInfo<FileInfoDTO> pageInfo = new PageInfo<>(fileInfoDTOs);
|
||||||
|
return new SuccessResultList<>(fileInfoDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置查询文件类型
|
||||||
|
*
|
||||||
|
* @param params
|
||||||
|
*/
|
||||||
|
private void setQueryFileType(Map<String, Object> params) {
|
||||||
|
String fileType = (String) params.get("fileType");
|
||||||
|
if (StringUtils.isBlank(fileType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<String> fileTypes;
|
||||||
|
if (StringUtils.equals("image", fileType)) {
|
||||||
|
fileTypes = Arrays.asList(fileComponent.getImageTypes());
|
||||||
|
} else if (StringUtils.equals("video", fileType)) {
|
||||||
|
fileTypes = Arrays.asList(fileComponent.getVideoTypes());
|
||||||
|
} else if (StringUtils.equals("audio", fileType)) {
|
||||||
|
fileTypes = Arrays.asList(fileComponent.getAudioTypes());
|
||||||
|
} else if (StringUtils.equals("file", fileType)) {
|
||||||
|
fileTypes = Arrays.asList(fileComponent.getFileTypes());
|
||||||
|
} else {
|
||||||
|
fileTypes = new ArrayList<>();
|
||||||
|
}
|
||||||
|
params.put("fileTypes", fileTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置下载次数
|
||||||
|
*
|
||||||
|
* @param fileInfoDTOs
|
||||||
|
*/
|
||||||
|
private void setDownloadCount(List<FileInfoDTO> fileInfoDTOs) {
|
||||||
|
fileInfoDTOs.forEach(fileInfoDTO -> {
|
||||||
|
Integer downloadCount = fileDownloadService.countByFileId(fileInfoDTO.getFileId());
|
||||||
|
fileInfoDTO.setDownloadCount(downloadCount);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件保存VO
|
* 获取文件保存VO
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package ink.wgink.module.file.startup;
|
||||||
|
|
||||||
|
import ink.wgink.interfaces.manager.IFilesShowCodeService;
|
||||||
|
import ink.wgink.module.file.manager.FilesManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName: FileStartUp
|
||||||
|
* @Description: 文件启动类
|
||||||
|
* @Author: wanggeng
|
||||||
|
* @Date: 2022/8/1 16:17
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class FilesStartUp implements ApplicationRunner {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IFilesShowCodeService filesShowCodeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
FilesManager.getInstance().setFilesShowCodeService(filesShowCodeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0/1 * * * ?")
|
||||||
|
public void clearTimeoutShowCode() {
|
||||||
|
FilesManager.getInstance().clearTimeoutShowCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="ink.wgink.module.file.dao.filedownload.IFileDownloadDao">
|
||||||
|
|
||||||
|
<resultMap id="fileDownloadDTO" type="ink.wgink.module.file.pojo.dtos.filedownload.FileDownloadDTO">
|
||||||
|
<id property="fileDownloadId" column="file_download_id"/>
|
||||||
|
<result property="fileId" column="file_id"/>
|
||||||
|
<result property="clientIp" column="client_ip"/>
|
||||||
|
<result property="gmtCreate" column="gmt_create"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 建表 -->
|
||||||
|
<update id="createTable">
|
||||||
|
CREATE TABLE IF NOT EXISTS `sys_file_download` (
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`file_download_id` char(36) DEFAULT NULL COMMENT '主键',
|
||||||
|
`file_id` char(36) DEFAULT NULL COMMENT '文件ID',
|
||||||
|
`client_ip` varchar(20) DEFAULT NULL COMMENT '客户端IP',
|
||||||
|
`gmt_create` datetime DEFAULT NULL COMMENT '下载时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `file_download_id` (`file_download_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 保存文件 -->
|
||||||
|
<insert id="save" parameterType="map">
|
||||||
|
INSERT INTO sys_file_download (
|
||||||
|
file_download_id,
|
||||||
|
file_id,
|
||||||
|
client_ip,
|
||||||
|
gmt_create
|
||||||
|
) VALUES(
|
||||||
|
#{fileDownloadId},
|
||||||
|
#{fileId},
|
||||||
|
#{clientIp},
|
||||||
|
#{gmtCreate}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<!-- 文件列表 -->
|
||||||
|
<select id="list" parameterType="map" resultMap="fileDownloadDTO">
|
||||||
|
SELECT
|
||||||
|
file_download_id,
|
||||||
|
file_id,
|
||||||
|
client_ip,
|
||||||
|
gmt_create
|
||||||
|
FROM
|
||||||
|
sys_file_download
|
||||||
|
WHERE
|
||||||
|
file_id = #{fileId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 统计 -->
|
||||||
|
<select id="count" parameterType="map" resultType="java.lang.Integer">
|
||||||
|
SELECT
|
||||||
|
COUNT(*)
|
||||||
|
FROM
|
||||||
|
sys_file_download
|
||||||
|
WHERE
|
||||||
|
file_id = #{fileId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
@ -283,6 +283,13 @@
|
|||||||
#{fileIds[${index}]}
|
#{fileIds[${index}]}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
|
<if test="fileTypes != null and fileTypes.size > 0">
|
||||||
|
AND
|
||||||
|
file_type IN
|
||||||
|
<foreach collection="fileTypes" index="index" open="(" separator="," close=")">
|
||||||
|
#{fileTypes[${index}]}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 文件列表 -->
|
<!-- 文件列表 -->
|
||||||
|
121
module-file/src/main/resources/templates/file-download/list.html
Normal file
121
module-file/src/main/resources/templates/file-download/list.html
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<base th:href="${#request.getContextPath() + '/'} ">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="renderer" content="webkit">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||||
|
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
|
||||||
|
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
|
||||||
|
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
|
||||||
|
<link rel="stylesheet" type="text/css" href="assets/js/vendor/viewer/viewer.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layui-anim layui-anim-fadein">
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-col-md12">
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-body" id="cardBody">
|
||||||
|
<table class="layui-hide" id="dataTable" lay-filter="dataTable"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/layuiadmin/layui/layui.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
layui.config({
|
||||||
|
base: 'assets/layuiadmin/'
|
||||||
|
}).extend({
|
||||||
|
index: 'lib/index'
|
||||||
|
}).use(['index', 'table', 'laydate', 'common'], function() {
|
||||||
|
var $ = layui.$;
|
||||||
|
var $win = $(window);
|
||||||
|
var table = layui.table;
|
||||||
|
var admin = layui.admin;
|
||||||
|
var laydate = layui.laydate;
|
||||||
|
var common = layui.common;
|
||||||
|
var resizeTimeout = null;
|
||||||
|
var fileId = top.restAjax.params(window.location.href).fileId;
|
||||||
|
var tableUrl = 'api/file-download/listpage/file-id/{fileId}';
|
||||||
|
|
||||||
|
// 初始化表格
|
||||||
|
function initTable() {
|
||||||
|
table.render({
|
||||||
|
elem: '#dataTable',
|
||||||
|
id: 'dataTable',
|
||||||
|
url: top.restAjax.path(tableUrl, [fileId]),
|
||||||
|
width: admin.screen() > 1 ? '100%' : '',
|
||||||
|
height: $win.height() - 20,
|
||||||
|
limit: 20,
|
||||||
|
limits: [20, 40, 60, 80, 100, 200],
|
||||||
|
request: {
|
||||||
|
pageName: 'page',
|
||||||
|
limitName: 'rows'
|
||||||
|
},
|
||||||
|
cols: [
|
||||||
|
[
|
||||||
|
{field: 'rowNum', width: 80, title: '序号', fixed: 'left', align: 'center', templet: '<span>{{d.LAY_INDEX}}</span>'},
|
||||||
|
{field: 'clientIp', width: 200, title: '客户端地址', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'gmtCreate', width: 180, title: '下载时间', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
],
|
||||||
|
page: true,
|
||||||
|
parseData: function (data) {
|
||||||
|
return {
|
||||||
|
'code': 0,
|
||||||
|
'msg': '',
|
||||||
|
'count': data.total,
|
||||||
|
'data': data.rows
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重载表格
|
||||||
|
function reloadTable(currentPage) {
|
||||||
|
table.reload('dataTable', {
|
||||||
|
url: top.restAjax.path(tableUrl, []),
|
||||||
|
where: {
|
||||||
|
keywords: $('#keywords').val(),
|
||||||
|
startTime: $('#startTime').val(),
|
||||||
|
endTime: $('#endTime').val()
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
curr: currentPage
|
||||||
|
},
|
||||||
|
height: $win.height() - 90,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initTable();
|
||||||
|
|
||||||
|
// 事件 - 页面变化
|
||||||
|
$win.on('resize', function () {
|
||||||
|
clearTimeout(resizeTimeout);
|
||||||
|
resizeTimeout = setTimeout(function () {
|
||||||
|
reloadTable();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
290
module-file/src/main/resources/templates/file/v2/list.html
Normal file
290
module-file/src/main/resources/templates/file/v2/list.html
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<base th:href="${#request.getContextPath() + '/'} ">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="renderer" content="webkit">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||||
|
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
|
||||||
|
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
|
||||||
|
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
|
||||||
|
<link rel="stylesheet" type="text/css" href="assets/js/vendor/viewer/viewer.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layui-fluid layui-anim layui-anim-fadein">
|
||||||
|
<div class="layui-row">
|
||||||
|
<div class="layui-col-md12">
|
||||||
|
<div class="layui-card">
|
||||||
|
<div class="layui-card-body" id="cardBody">
|
||||||
|
<div class="test-table-reload-btn" style="margin-bottom: 10px;">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<input type="text" id="keywords" class="layui-input search-item" placeholder="输入文件名">
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline layui-form search-item">
|
||||||
|
<select id="fileType" name="fileType">
|
||||||
|
<option value="">选择类型</option>
|
||||||
|
<option value="image">图片</option>
|
||||||
|
<option value="video">视频</option>
|
||||||
|
<option value="audio">音频</option>
|
||||||
|
<option value="file">文件</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="search" class="layui-btn layui-btn-sm">
|
||||||
|
<i class="fa fa-lg fa-search"></i> 搜索
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<table class="layui-hide" id="dataTable" lay-filter="dataTable"></table>
|
||||||
|
<!-- 表头按钮组 -->
|
||||||
|
<script type="text/html" id="headerToolBar">
|
||||||
|
<div class="layui-btn-group">
|
||||||
|
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm" lay-event="removeEvent">
|
||||||
|
<i class="fa fa-lg fa-trash"></i> 删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="assets/layuiadmin/layui/layui.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
layui.config({
|
||||||
|
base: 'assets/layuiadmin/'
|
||||||
|
}).extend({
|
||||||
|
index: 'lib/index'
|
||||||
|
}).use(['index', 'table', 'laydate', 'common'], function() {
|
||||||
|
var $ = layui.$;
|
||||||
|
var $win = $(window);
|
||||||
|
var table = layui.table;
|
||||||
|
var admin = layui.admin;
|
||||||
|
var laydate = layui.laydate;
|
||||||
|
var common = layui.common;
|
||||||
|
var resizeTimeout = null;
|
||||||
|
var tableUrl = 'api/file/v2/listpage';
|
||||||
|
var previewTypeArray = [
|
||||||
|
'png','jpg','jpeg','gif','blob',
|
||||||
|
'mp4',
|
||||||
|
'mp3', 'wav',
|
||||||
|
'pdf'
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是预览类型
|
||||||
|
* @param fileType
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
function isPreviewType(fileType) {
|
||||||
|
for(var i = 0, item; item = previewTypeArray[i++];) {
|
||||||
|
if(fileType.toLowerCase() == item) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化表格
|
||||||
|
function initTable() {
|
||||||
|
table.render({
|
||||||
|
elem: '#dataTable',
|
||||||
|
id: 'dataTable',
|
||||||
|
url: top.restAjax.path(tableUrl, []),
|
||||||
|
width: admin.screen() > 1 ? '100%' : '',
|
||||||
|
height: $win.height() - 90,
|
||||||
|
limit: 20,
|
||||||
|
limits: [20, 40, 60, 80, 100, 200],
|
||||||
|
toolbar: '#headerToolBar',
|
||||||
|
request: {
|
||||||
|
pageName: 'page',
|
||||||
|
limitName: 'rows'
|
||||||
|
},
|
||||||
|
cols: [
|
||||||
|
[
|
||||||
|
{type: 'checkbox', fixed: 'left'},
|
||||||
|
{field: 'rowNum', width: 80, title: '序号', fixed: 'left', align: 'center', templet: '<span>{{d.LAY_INDEX}}</span>'},
|
||||||
|
{field: 'fileId', width: 300, title: '主键', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'fileName', width: 200, title: '文件名称', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'filePath', width: 300, title: '存放位置', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'fileUrl', width: 300, title: '访问地址', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'fileType', width: 100, title: '文件类型', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'fileSize', width: 120, title: '文件大小', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'fileSummary', width: 200, title: '文件描述', align: 'center',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'preview', width: 90, title: '预览', align: 'center', fixed: 'right',
|
||||||
|
templet: function (row) {
|
||||||
|
if(isPreviewType(row.fileType)) {
|
||||||
|
return '<a href="route/file/v2/download/true/'+ row.fileId +'" target="_blank" title="点击预览" class="layui-btn layui-btn-xs" ><i class="fa fa-eye" aria-hidden="true"></i> 预览</a>'
|
||||||
|
}
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'download', width: 90, title: '下载', align: 'center', fixed: 'right',
|
||||||
|
templet: function (row) {
|
||||||
|
return '<a href="route/file/v2/download/false/'+ row.fileId +'" target="_blank" title="点击下载" class="layui-btn layui-btn-xs layui-btn-normal" ><i class="fa fa-cloud-download" aria-hidden="true"></i> 下载</a>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{field: 'downloadCount', width: 100, title: '下载次数', align: 'center', fixed: 'right',
|
||||||
|
templet: function (row) {
|
||||||
|
var rowData = row[this.field];
|
||||||
|
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
if(rowData == 0) {
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
return '<button class="layui-btn layui-btn-xs layui-btn-danger" lay-event="showDownloadFilter">'+ rowData +'次</button>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
],
|
||||||
|
page: true,
|
||||||
|
parseData: function (data) {
|
||||||
|
return {
|
||||||
|
'code': 0,
|
||||||
|
'msg': '',
|
||||||
|
'count': data.total,
|
||||||
|
'data': data.rows
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重载表格
|
||||||
|
function reloadTable(currentPage) {
|
||||||
|
table.reload('dataTable', {
|
||||||
|
url: top.restAjax.path(tableUrl, []),
|
||||||
|
where: {
|
||||||
|
keywords: $('#keywords').val(),
|
||||||
|
fileType: $('#fileType').val()
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
curr: currentPage
|
||||||
|
},
|
||||||
|
height: $win.height() - 90,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteData(ids) {
|
||||||
|
top.dialog.confirm('删除记录与源文件', function() {
|
||||||
|
var layIndex;
|
||||||
|
top.restAjax.delete(top.restAjax.path('api/file/v2/delete/{ids}', [ids]), {}, null, function (code, data) {
|
||||||
|
top.dialog.msg('删除成功', {time: 1000});
|
||||||
|
reloadTable();
|
||||||
|
}, function (code, data) {
|
||||||
|
top.dialog.msg(data.msg);
|
||||||
|
}, function () {
|
||||||
|
layIndex = top.dialog.msg(top.dataMessage.deleting, {icon: 16, time: 0, shade: 0.3});
|
||||||
|
}, function () {
|
||||||
|
top.dialog.close(layIndex);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initTable();
|
||||||
|
|
||||||
|
// 事件 - 页面变化
|
||||||
|
$win.on('resize', function () {
|
||||||
|
clearTimeout(resizeTimeout);
|
||||||
|
resizeTimeout = setTimeout(function () {
|
||||||
|
reloadTable();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
// 事件 - 搜索
|
||||||
|
$(document).on('click', '#search', function () {
|
||||||
|
reloadTable(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 事件 - 增删改
|
||||||
|
table.on('toolbar(dataTable)', function (obj) {
|
||||||
|
var layEvent = obj.event;
|
||||||
|
var checkStatus = table.checkStatus('dataTable');
|
||||||
|
var checkDatas = checkStatus.data;
|
||||||
|
if (layEvent === 'removeEvent') {
|
||||||
|
if (checkDatas.length === 0) {
|
||||||
|
top.dialog.msg(top.dataMessage.table.selectDelete);
|
||||||
|
} else {
|
||||||
|
var ids = '';
|
||||||
|
for (var i = 0, item; item = checkDatas[i++];) {
|
||||||
|
if (i > 1) {
|
||||||
|
ids += '_';
|
||||||
|
}
|
||||||
|
ids += item['fileId'];
|
||||||
|
}
|
||||||
|
deleteData(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
table.on('tool(dataTable)', function(obj) {
|
||||||
|
var data = obj.data;
|
||||||
|
var event = obj.event;
|
||||||
|
if(event === 'showDownloadFilter') {
|
||||||
|
top.dialog.open({
|
||||||
|
title: '下载记录',
|
||||||
|
url: top.restAjax.path('route/file-download/list?fileId={fileId}', [data.fileId]),
|
||||||
|
width: '500px',
|
||||||
|
height: '500px',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user