增加文件中心与客户端功能,增加文件远程上传与下载功能

This commit is contained in:
wanggeng 2022-08-07 22:02:03 +08:00
parent 4354516b20
commit f7468f77fd
25 changed files with 1845 additions and 141 deletions

View File

@ -1,10 +1,8 @@
package ink.wgink.module.file.components;
import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.module.file.enums.UploadTypeEnum;
import ink.wgink.module.file.service.IFileService;
import ink.wgink.properties.FileProperties;
import ink.wgink.util.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
@ -14,12 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @ClassName: FileUtil
@ -32,106 +24,13 @@ import java.security.NoSuchAlgorithmException;
public class FileComponent {
protected static final Logger LOG = LoggerFactory.getLogger(FileComponent.class);
private static final char[] HEX_CODE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
private String[] imageTypes;
private String[] videoTypes;
private String[] audioTypes;
private String[] fileTypes;
private String[] imageTypes = null;
private String[] videoTypes = null;
private String[] audioTypes = null;
private String[] fileTypes = null;
@Autowired
private FileProperties fileProperties;
/**
* 保存文件
*
* @param fileInputStream
* @param fileName
* @param filePath
* @return
*/
public long saveFile(InputStream fileInputStream, String fileName, String filePath) {
File uploadFolder = new File(filePath);
if (!uploadFolder.exists()) {
uploadFolder.mkdirs();
}
FileOutputStream uploadFileOutputStream = null;
long fileSize = 0;
try {
uploadFileOutputStream = new FileOutputStream(uploadFolder + File.separator + fileName);
int readLength;
for (byte[] buf = new byte[IFileService.INPUT_STREAM_SIZE]; (readLength = fileInputStream.read(buf)) > -1; ) {
uploadFileOutputStream.write(buf, 0, readLength);
fileSize += readLength;
}
uploadFileOutputStream.flush();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new FileException("文件上传失败");
} finally {
try {
if (null != uploadFileOutputStream) {
uploadFileOutputStream.close();
}
if (null != fileInputStream) {
fileInputStream.close();
}
} catch (Exception e1) {
LOG.error(e1.getMessage());
throw new FileException("文件上传失败");
}
}
return fileSize;
}
/**
* 删除源文件
*
* @param sourceFilePath
*/
public static void deleteSourceFile(String sourceFilePath) {
File file = new File(sourceFilePath);
if (file.exists()) {
boolean isDelete = file.delete();
if (isDelete) {
LOG.debug("文件删除成功");
} else {
LOG.debug("文件删除失败");
}
}
}
/**
* 获取文件的MD5
*
* @param file
* @return
*/
public String getFileMD5(File file) {
if (file == null) {
throw new SearchException("文件不存在");
}
if (!file.exists()) {
throw new SearchException("文件不存在");
}
String fileMd5;
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
int readLength;
for (byte[] buf = new byte[IFileService.INPUT_STREAM_SIZE]; (readLength = inputStream.read(buf)) > -1; ) {
messageDigest.update(buf, 0, readLength);
}
// 计算文件的MD5
byte[] data = messageDigest.digest();
StringBuilder fileMd5SB = new StringBuilder(data.length * 2);
for (byte b : data) {
fileMd5SB.append(HEX_CODE[(b >> 4) & 0xF]);
fileMd5SB.append(HEX_CODE[(b & 0xF)]);
}
fileMd5 = fileMd5SB.toString();
} catch (IOException | NoSuchAlgorithmException e) {
throw new SystemException(e);
}
return fileMd5;
}
/**
* 获取上传绝对文件

View File

@ -0,0 +1,104 @@
package ink.wgink.module.file.controller.api.fileclient;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.file.pojo.dtos.fileclient.FileClientDTO;
import ink.wgink.module.file.pojo.vos.fileremote.FileClientVO;
import ink.wgink.module.file.service.fileclient.IFileClientService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResult;
import ink.wgink.pojo.result.SuccessResultList;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @ClassName: FileClientController
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 22:18
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件客户端接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/file-client")
public class FileClientController extends DefaultBaseController {
@Autowired
private IFileClientService fileRemoteService;
@ApiOperation(value = "新增", notes = "新增接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("save")
@CheckRequestBodyAnnotation
public SuccessResult save(@RequestBody FileClientVO fileClientVO) {
fileRemoteService.save(fileClientVO);
return new SuccessResult();
}
@ApiOperation(value = "删除(id列表)", notes = "删除(id列表)接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "ids", value = "ID列表用下划线分隔", paramType = "path", example = "1_2_3")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@DeleteMapping("remove/{ids}")
public SuccessResult remove(@PathVariable("ids") String ids) throws RemoveException {
fileRemoteService.remove(Arrays.asList(ids.split("\\_")));
return new SuccessResult();
}
@ApiOperation(value = "修改", notes = "修改接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "fileClientId", value = "主键", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PutMapping("update/{fileClientId}")
@CheckRequestBodyAnnotation
public SuccessResult update(@PathVariable("fileClientId") String fileClientId, @RequestBody FileClientVO fileClientVO) {
fileRemoteService.update(fileClientId, fileClientVO);
return new SuccessResult();
}
@ApiOperation(value = "详情(通过ID)", notes = "详情(通过ID)接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "fileClientId", value = "主键", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("get/{fileClientId}")
public FileClientDTO get(@PathVariable("fileClientId") String fileClientId) {
return fileRemoteService.get(fileClientId);
}
@ApiOperation(value = "列表", notes = "列表接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("list")
public List<FileClientDTO> list() throws SearchException {
Map<String, Object> params = requestParams();
return fileRemoteService.list(params);
}
@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"),
@ApiImplicitParam(name = "startTime", value = "开始时间", paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "endTime", value = "结束时间", paramType = "query", dataType = "String")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("listpage")
public SuccessResultList<List<FileClientDTO>> listPage(ListPage page) throws SearchException {
Map<String, Object> params = requestParams();
page.setParams(params);
return fileRemoteService.listPage(page);
}
}

View File

@ -13,9 +13,18 @@ import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.pojo.result.SuccessResultList;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -45,6 +54,66 @@ public class FileController extends DefaultBaseController {
return uploadSingle(file, UploadTypeEnum.FILE);
}
@ApiOperation(value = "上传文件", notes = "上传文件接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件name", paramType = "query")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("upload-file-inputstream")
public SuccessResultData<FileUploadSuccessDTO> uploadFileInputStream(@RequestParam("file") MultipartFile file) throws IOException {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:7008/study/api/file/v2/upload-file";
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
InputStreamResource inputStreamResource = new InputStreamResource(file.getInputStream()) {
@Override
public String getFilename() {
return file.getOriginalFilename();
}
@Override
public long contentLength() {
return file.getSize();
}
};
params.add("file", inputStreamResource);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
String result = restTemplate.postForObject(url, requestEntity, String.class);
System.out.println(result);
return new SuccessResultData<>();
}
@ApiOperation(value = "上传文件", notes = "上传文件接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "文件name", paramType = "query")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("upload-file-bytearray")
public SuccessResultData<FileUploadSuccessDTO> uploadFileByteArray(@RequestParam("file") MultipartFile file) throws IOException {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:7008/study/api/file/v2/upload-file";
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) {
@Override
public String getFilename() {
return file.getOriginalFilename();
}
@Override
public long contentLength() {
return file.getSize();
}
};
params.add("file", fileAsResource);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
String result = restTemplate.postForObject(url, requestEntity, String.class);
System.out.println(result);
return new SuccessResultData<>();
}
@ApiOperation(value = "上传图片", notes = "上传图片接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "image", value = "文件name", paramType = "query")

View File

@ -0,0 +1,114 @@
package ink.wgink.module.file.controller.app.api.filecenter;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.file.enums.UploadTypeEnum;
import ink.wgink.module.file.manager.FileRemoteManager;
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
import ink.wgink.module.file.service.filecenter.IFileCenterService;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResultData;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* @ClassName: FileAppCenterController
* @Description: APP文件远程
* @Author: WangGeng
* @Date: 2019-08-02 15:38
* @Version: 1.0
**/
@Api(tags = ISystemConstant.API_TAGS_APP_PREFIX + "文件远程调用接口")
@RestController("fileAppCenterControllerV2")
@RequestMapping(ISystemConstant.APP_PREFIX + "/file-center")
public class FileCenterAppController extends DefaultBaseController {
@Autowired
private IFileCenterService fileCenterService;
@ApiOperation(value = "上传文件", notes = "上传文件接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "Access-Key", value = "Access-Key", paramType = "header"),
@ApiImplicitParam(name = "Access-Secret", value = "Access-Secret", paramType = "header"),
@ApiImplicitParam(name = "file", value = "文件", paramType = "form"),
@ApiImplicitParam(name = "creator", value = "创建人", paramType = "form")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("upload-file")
public SuccessResultData<FileUploadSuccessDTO> uploadFile(@RequestHeader("Access-Key") String accessKey,
@RequestHeader("Access-Secret") String accessSecret,
@RequestParam("file") MultipartFile file,
@RequestParam("creator") String creator) {
checkKeyAndSecret(accessKey, accessSecret);
return new SuccessResultData<>(fileCenterService.uploadSingleByUserId(creator, file, UploadTypeEnum.FILE));
}
@ApiOperation(value = "上传图片", notes = "上传图片接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "Access-Key", value = "Access-Key", paramType = "header"),
@ApiImplicitParam(name = "Access-Secret", value = "Access-Secret", paramType = "header"),
@ApiImplicitParam(name = "image", value = "图片", paramType = "form"),
@ApiImplicitParam(name = "creator", value = "创建人", paramType = "form")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("upload-image")
public SuccessResultData<FileUploadSuccessDTO> uploadImage(@RequestHeader("Access-Key") String accessKey,
@RequestHeader("Access-Secret") String accessSecret,
@RequestParam("image") MultipartFile image,
@RequestParam("creator") String creator) {
checkKeyAndSecret(accessKey, accessSecret);
return new SuccessResultData<>(fileCenterService.uploadSingleByUserId(creator, image, UploadTypeEnum.IMAGE));
}
@ApiOperation(value = "上传视频", notes = "上传视频接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "Access-Key", value = "Access-Key", paramType = "header"),
@ApiImplicitParam(name = "Access-Secret", value = "Access-Secret", paramType = "header"),
@ApiImplicitParam(name = "video", value = "视频", paramType = "form"),
@ApiImplicitParam(name = "creator", value = "创建人", paramType = "form")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("upload-video")
public SuccessResultData<FileUploadSuccessDTO> uploadVideo(@RequestHeader("Access-Key") String accessKey,
@RequestHeader("Access-Secret") String accessSecret,
@RequestParam("video") MultipartFile video,
@RequestParam("creator") String creator) {
checkKeyAndSecret(accessKey, accessSecret);
return new SuccessResultData<>(fileCenterService.uploadSingleByUserId(creator, video, UploadTypeEnum.VIDEO));
}
@ApiOperation(value = "上传音频", notes = "上传音频接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "Access-Key", value = "Access-Key", paramType = "header"),
@ApiImplicitParam(name = "Access-Secret", value = "Access-Secret", paramType = "header"),
@ApiImplicitParam(name = "audio", value = "音频", paramType = "form"),
@ApiImplicitParam(name = "creator", value = "创建人", paramType = "form")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("upload-audio")
public SuccessResultData<FileUploadSuccessDTO> uploadAudio(@RequestHeader("Access-Key") String accessKey,
@RequestHeader("Access-Secret") String accessSecret,
@RequestParam("audio") MultipartFile audio,
@RequestParam("creator") String creator) {
checkKeyAndSecret(accessKey, accessSecret);
return new SuccessResultData<>(fileCenterService.uploadSingleByUserId(creator, audio, UploadTypeEnum.AUDIO));
}
/**
* 校验Key与Secret
*
* @param accessKey
* @param accessSecret
*/
private void checkKeyAndSecret(String accessKey, String accessSecret) {
if (!FileRemoteManager.getInstance().check(accessKey, accessSecret)) {
throw new ParamsException("Key与Secret不匹配");
}
}
}

View File

@ -0,0 +1,40 @@
package ink.wgink.module.file.controller.route.fileclient;
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: FileRemoteRouteController
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 22:23
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "文件远程")
@Controller
@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/file-client")
public class FileClientRouteController {
@GetMapping("list")
public ModelAndView list() {
ModelAndView modelAndView = new ModelAndView("file-client/list");
return modelAndView;
}
@GetMapping("save")
public ModelAndView save() {
ModelAndView modelAndView = new ModelAndView("file-client/save");
return modelAndView;
}
@GetMapping("update")
public ModelAndView update() {
ModelAndView modelAndView = new ModelAndView("file-client/update");
return modelAndView;
}
}

View File

@ -0,0 +1,65 @@
package ink.wgink.module.file.dao.fileclient;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SaveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.interfaces.init.IInitBaseTable;
import ink.wgink.module.file.pojo.dtos.fileclient.FileClientDTO;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* @ClassName: IFileRemoteDao
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 20:53
* @Version: 1.0
*/
@Repository
public interface IFileClientDao extends IInitBaseTable {
/**
* 新增
*
* @param params
* @throws SaveException
*/
void save(Map<String, Object> params) throws SaveException;
/**
* @param params
* @throws RemoveException
*/
void remove(Map<String, Object> params) throws RemoveException;
/**
* 修改状态
*
* @param params
* @throws UpdateException
*/
void update(Map<String, Object> params) throws UpdateException;
/**
* 详情
*
* @param params
* @return
* @throws SearchException
*/
FileClientDTO get(Map<String, Object> params) throws SearchException;
/**
* 列表
*
* @param params
* @return
* @throws SearchException
*/
List<FileClientDTO> list(Map<String, Object> params) throws SearchException;
}

View File

@ -0,0 +1,70 @@
package ink.wgink.module.file.manager;
import ink.wgink.module.file.dao.fileclient.IFileClientDao;
import ink.wgink.module.file.pojo.dtos.fileclient.FileClientDTO;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName: FileRemoteManager
* @Description: 文件远程管理
* @Author: wanggeng
* @Date: 2022/8/4 23:16
* @Version: 1.0
*/
public class FileRemoteManager {
private static FileRemoteManager fileRemoteManager = FileRemoteManagerBuilder.fileRemoteManager;
private Map<String, String> updateKeyValueMap = new ConcurrentHashMap<>();
private IFileClientDao fileRemoteDao;
private FileRemoteManager() {
}
public static FileRemoteManager getInstance() {
return fileRemoteManager;
}
public void refresh() {
updateKeyValueMap.clear();
Map<String, Object> params = new HashMap<>();
params.put("status", "active");
List<FileClientDTO> fileClientDTOS = fileRemoteDao.list(params);
for (FileClientDTO fileClientDTO : fileClientDTOS) {
updateKeyValueMap.put(fileClientDTO.getAccessKey(), fileClientDTO.getAccessSecret());
}
}
/**
* 校验
*
* @param updateKey
* @param updateSecret
* @return
*/
public boolean check(String updateKey, String updateSecret) {
if (StringUtils.isBlank(updateKey) || StringUtils.isBlank(updateSecret)) {
return false;
}
String existUpdateSecret = updateKeyValueMap.get(updateKey);
if (!StringUtils.equals(updateSecret, existUpdateSecret)) {
return false;
}
return true;
}
public void setFileRemoteDao(IFileClientDao fileRemoteDao) {
this.fileRemoteDao = fileRemoteDao;
refresh();
}
private static class FileRemoteManagerBuilder {
public static FileRemoteManager fileRemoteManager = new FileRemoteManager();
}
}

View File

@ -0,0 +1,76 @@
package ink.wgink.module.file.pojo.dtos.fileclient;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* @ClassName: FileRemoteDTO
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 20:56
* @Version: 1.0
*/
@ApiModel
public class FileClientDTO {
@ApiModelProperty(name = "fileClientId", value = "主键")
private String fileClientId;
@ApiModelProperty(name = "title", value = "标题")
private String title;
@ApiModelProperty(name = "accessKey", value = "上传Key")
private String accessKey;
@ApiModelProperty(name = "accessSecret", value = "上传秘钥")
private String accessSecret;
@ApiModelProperty(name = "status", value = "状态")
private String status;
@ApiModelProperty(name = "gmtCreate", value = "创建时间")
private String gmtCreate;
public String getFileClientId() {
return fileClientId == null ? "" : fileClientId.trim();
}
public void setFileClientId(String fileClientId) {
this.fileClientId = fileClientId;
}
public String getTitle() {
return title == null ? "" : title.trim();
}
public void setTitle(String title) {
this.title = title;
}
public String getAccessKey() {
return accessKey == null ? "" : accessKey.trim();
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getAccessSecret() {
return accessSecret == null ? "" : accessSecret.trim();
}
public void setAccessSecret(String accessSecret) {
this.accessSecret = accessSecret;
}
public String getStatus() {
return status == null ? "" : status.trim();
}
public void setStatus(String status) {
this.status = status;
}
public String getGmtCreate() {
return gmtCreate == null ? "" : gmtCreate.trim();
}
public void setGmtCreate(String gmtCreate) {
this.gmtCreate = gmtCreate;
}
}

View File

@ -0,0 +1,39 @@
package ink.wgink.module.file.pojo.vos.fileremote;
import ink.wgink.annotation.CheckEmptyAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* @ClassName: FileRemoteVO
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 21:35
* @Version: 1.0
*/
@ApiModel
public class FileClientVO {
@ApiModelProperty(name = "title", value = "标题")
@CheckEmptyAnnotation(name = "标题")
private String title;
@ApiModelProperty(name = "status", value = "状态")
@CheckEmptyAnnotation(name = "状态")
private String status;
public String getTitle() {
return title == null ? "" : title.trim();
}
public void setTitle(String title) {
this.title = title;
}
public String getStatus() {
return status == null ? "" : status.trim();
}
public void setStatus(String status) {
this.status = status;
}
}

View File

@ -12,8 +12,10 @@ public class FileSaveVO {
private String fileName;
private String fileType;
private String uploadPath;
private String fileUrl;
private long fileSize;
private String creator;
private String fileSummary;
public String getFileName() {
return fileName == null ? "" : fileName.trim();
@ -39,6 +41,14 @@ public class FileSaveVO {
this.uploadPath = uploadPath;
}
public String getFileUrl() {
return fileUrl == null ? "" : fileUrl.trim();
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
public long getFileSize() {
return fileSize;
}
@ -54,4 +64,12 @@ public class FileSaveVO {
public void setCreator(String creator) {
this.creator = creator;
}
public String getFileSummary() {
return fileSummary == null ? "" : fileSummary.trim();
}
public void setFileSummary(String fileSummary) {
this.fileSummary = fileSummary;
}
}

View File

@ -0,0 +1,90 @@
package ink.wgink.module.file.remote;
import ink.wgink.annotation.rpc.rest.RemoteService;
import ink.wgink.annotation.rpc.rest.method.RemotePostMethod;
import ink.wgink.annotation.rpc.rest.params.RemoteFileInputStreamParams;
import ink.wgink.annotation.rpc.rest.params.RemoteFormParams;
import ink.wgink.annotation.rpc.rest.params.RemoteHeaderParams;
import ink.wgink.annotation.rpc.rest.params.RemoteServerParams;
import ink.wgink.common.rpc.rest.pojo.RemoteFileInputStream;
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
/**
* @ClassName: IFileCenterUploadService
* @Description: 文件中心上传
* @Author: wanggeng
* @Date: 2022/8/4 15:00
* @Version: 1.0
*/
@RemoteService
public interface IFileCenterRemoteService {
/**
* 上传文件
*
* @param server
* @param accessKey
* @param accessSecret
* @param remoteFileInputStream
* @param creator
* @return
*/
@RemotePostMethod("/app/file-center/upload-file")
FileUploadSuccessDTO uploadFile(@RemoteServerParams String server,
@RemoteHeaderParams("Access-Key") String accessKey,
@RemoteHeaderParams("Access-Secret") String accessSecret,
@RemoteFileInputStreamParams("file") RemoteFileInputStream remoteFileInputStream,
@RemoteFormParams("creator") String creator);
/**
* 上传图片
*
* @param server
* @param accessKey
* @param accessSecret
* @param remoteFileInputStream
* @param creator
* @return
*/
@RemotePostMethod("/app/file-center/upload-image")
FileUploadSuccessDTO uploadImage(@RemoteServerParams String server,
@RemoteHeaderParams("Access-Key") String accessKey,
@RemoteHeaderParams("Access-Secret") String accessSecret,
@RemoteFileInputStreamParams("image") RemoteFileInputStream remoteFileInputStream,
@RemoteFormParams("creator") String creator);
/**
* 上传音频
*
* @param server
* @param accessKey
* @param accessSecret
* @param remoteFileInputStream
* @param creator
* @return
*/
@RemotePostMethod("/app/file-center/upload-audio")
FileUploadSuccessDTO uploadAudio(@RemoteServerParams String server,
@RemoteHeaderParams("Access-Key") String accessKey,
@RemoteHeaderParams("Access-Secret") String accessSecret,
@RemoteFileInputStreamParams("audio") RemoteFileInputStream remoteFileInputStream,
@RemoteFormParams("creator") String creator);
/**
* 上传视频
*
* @param server
* @param accessKey
* @param accessSecret
* @param remoteFileInputStream
* @param creator
* @return
*/
@RemotePostMethod("/app/file-center/upload-video")
FileUploadSuccessDTO uploadVideo(@RemoteServerParams String server,
@RemoteHeaderParams("Access-Key") String accessKey,
@RemoteHeaderParams("Access-Secret") String accessSecret,
@RemoteFileInputStreamParams("video") RemoteFileInputStream remoteFileInputStream,
@RemoteFormParams("creator") String creator);
}

View File

@ -0,0 +1,27 @@
package ink.wgink.module.file.service.filecenter;
import ink.wgink.module.file.enums.UploadTypeEnum;
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
import org.springframework.web.multipart.MultipartFile;
/**
* @ClassName: IFileCenterService
* @Description: 文件中心
* @Author: wanggeng
* @Date: 2022/8/6 13:36
* @Version: 1.0
*/
public interface IFileCenterService {
/**
* 单文件上传
*
* @param userId
* @param uploadFile
* @param uploadTypeEnum
* @return
*/
FileUploadSuccessDTO uploadSingleByUserId(String userId, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum);
}

View File

@ -0,0 +1,116 @@
package ink.wgink.module.file.service.filecenter.impl;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.module.file.enums.UploadTypeEnum;
import ink.wgink.module.file.pojo.dtos.v2.FileUploadSuccessDTO;
import ink.wgink.module.file.pojo.vos.v2.FileSaveVO;
import ink.wgink.module.file.service.filecenter.IFileCenterService;
import ink.wgink.module.file.service.filedownload.IFileDownloadService;
import ink.wgink.module.file.service.v2.IFileService;
import ink.wgink.pojo.pos.FilePO;
import ink.wgink.util.request.StaticResourceRequestUtil;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.URLEncoder;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
/**
* @ClassName: FileCenterServiceImpl
* @Description: 文件中心
* @Author: wanggeng
* @Date: 2022/8/6 13:36
* @Version: 1.0
*/
@Service
public class FileCenterServiceImpl extends DefaultBaseService implements IFileCenterService {
@Autowired
private IFileService fileService;
@Autowired
private IFileDownloadService fileDownloadService;
@Override
public FileUploadSuccessDTO uploadSingleByUserId(String userId, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
FileSaveVO fileSaveVO = getCenterFileSaveVO(uploadFile, uploadTypeEnum, userId);
return fileService.saveFile(fileSaveVO);
}
private void download(HttpServletRequest request, HttpServletResponse response, String fileId) {
FilePO filePO = fileService.getPO(fileId);
try (
RandomAccessFile randomAccessFile = new RandomAccessFile(filePO.getFilePath(), "r");
FileChannel fileChannel = randomAccessFile.getChannel();
OutputStream outputStream = response.getOutputStream();
WritableByteChannel writableByteChannel = Channels.newChannel(outputStream);
) {
response.setHeader("Content-Length", filePO.getFileSize().toString());
response.setContentType(StaticResourceRequestUtil.getContentType(filePO.getFileType()));
response.setHeader("Content-Disposition", "inline;fileName=" + URLEncoder.encode(filePO.getFileName(), "UTF-8"));
String rangeString = request.getHeader("Range");
long contentLength = filePO.getFileSize();
long startRange = 0;
long endRange = contentLength - 1;
if (!StringUtils.isBlank(rangeString)) {
response.setContentType("multipart/byteranges");
String[] rangeArray = rangeString.substring(rangeString.indexOf("=") + 1).split("-");
startRange = Long.parseLong(rangeArray[0]);
if (rangeArray.length > 1) {
endRange = Long.parseLong(rangeArray[1]);
}
response.setHeader("Content-Length", String.valueOf(endRange - startRange + 1));
response.setHeader("Content-Range", String.format("bytes %d-%d/%d", startRange, endRange, contentLength));
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Etag", fileId);
response.setStatus(206);
randomAccessFile.seek(startRange);
}
LOG.debug("startRange: {}, endRange: {}", startRange, endRange);
long totalOutputLength = endRange - startRange + 1;
fileChannel.transferTo(startRange, totalOutputLength, writableByteChannel);
outputStream.flush();
if (endRange >= contentLength - 1) {
fileDownloadService.handle(request, false, fileId);
}
} catch (Exception e) {
e.printStackTrace();
if (e instanceof ClientAbortException) {
LOG.debug("客户端断开连接");
} else {
throw new FileException("文件输出异常", e);
}
}
}
/**
* 获取文件保存VO
*
* @param uploadFile
* @param uploadTypeEnum
* @return
*/
private FileSaveVO getCenterFileSaveVO(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, String creator) {
String fileName = uploadFile.getOriginalFilename();
InputStream inputStream;
try {
inputStream = uploadFile.getInputStream();
} catch (IOException e) {
throw new SearchException(e);
}
return fileService.getCenterFileSaveVO(inputStream, uploadTypeEnum, fileName, creator);
}
}

View File

@ -0,0 +1,73 @@
package ink.wgink.module.file.service.fileclient;
import ink.wgink.module.file.pojo.dtos.fileclient.FileClientDTO;
import ink.wgink.module.file.pojo.vos.fileremote.FileClientVO;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import java.util.List;
import java.util.Map;
/**
* @ClassName: IFileRemoteService
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 21:32
* @Version: 1.0
*/
public interface IFileClientService {
/**
* 保存
*
* @param fileClientVO
*/
void save(FileClientVO fileClientVO);
/**
* 删除
*
* @param ids
*/
void remove(List<String> ids);
/**
* 更新状态
*
* @param fileRemoteId
* @param fileClientVO
*/
void update(String fileRemoteId, FileClientVO fileClientVO);
/**
* 详情
*
* @param params
* @return
*/
FileClientDTO get(Map<String, Object> params);
/**
* 详情
*
* @param fileRemoteId
* @return
*/
FileClientDTO get(String fileRemoteId);
/**
* 列表
*
* @param params
* @return
*/
List<FileClientDTO> list(Map<String, Object> params);
/**
* 分页列表
*
* @param page
* @return
*/
SuccessResultList<List<FileClientDTO>> listPage(ListPage page);
}

View File

@ -0,0 +1,91 @@
package ink.wgink.module.file.service.fileclient.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.module.file.dao.fileclient.IFileClientDao;
import ink.wgink.module.file.manager.FileRemoteManager;
import ink.wgink.module.file.pojo.dtos.fileclient.FileClientDTO;
import ink.wgink.module.file.pojo.vos.fileremote.FileClientVO;
import ink.wgink.module.file.service.fileclient.IFileClientService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.UUIDUtil;
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: FileRemoteServiceImpl
* @Description: 文件远程
* @Author: wanggeng
* @Date: 2022/8/4 21:33
* @Version: 1.0
*/
@Service
public class FileClientServiceImpl extends DefaultBaseService implements IFileClientService {
@Autowired
private IFileClientDao fileRemoteDao;
@Override
public void save(FileClientVO fileClientVO) {
Map<String, Object> params = HashMapUtil.beanToMap(fileClientVO);
params.put("fileClientId", UUIDUtil.getUUID());
params.put("accessKey", UUIDUtil.getUUID());
params.put("accessSecret", UUIDUtil.get32UUID() + UUIDUtil.get32UUID());
setSaveInfo(params);
params.put("isDelete", 0);
fileRemoteDao.save(params);
FileRemoteManager.getInstance().refresh();
}
@Override
public void remove(List<String> ids) {
Map<String, Object> params = getHashMap(2);
params.put("fileClientIds", ids);
fileRemoteDao.remove(params);
FileRemoteManager.getInstance().refresh();
}
@Override
public void update(String fileClientId, FileClientVO fileClientVO) {
Map<String, Object> params = HashMapUtil.beanToMap(fileClientVO);
params.put("fileClientId", fileClientId);
setUpdateInfo(params);
fileRemoteDao.update(params);
FileRemoteManager.getInstance().refresh();
}
@Override
public FileClientDTO get(Map<String, Object> params) {
params = params == null ? getHashMap(0) : params;
return fileRemoteDao.get(params);
}
@Override
public FileClientDTO get(String fileClientId) {
Map<String, Object> params = getHashMap(2);
params.put("fileClientId", fileClientId);
return fileRemoteDao.get(params);
}
@Override
public List<FileClientDTO> list(Map<String, Object> params) {
return fileRemoteDao.list(params);
}
@Override
public SuccessResultList<List<FileClientDTO>> listPage(ListPage page) {
PageHelper.startPage(page.getPage(), page.getRows());
List<FileClientDTO> fileClientDTOS = list(page.getParams());
PageInfo<FileClientDTO> pageInfo = new PageInfo<>(fileClientDTOS);
return new SuccessResultList<>(fileClientDTOS, pageInfo.getPageNum(), pageInfo.getTotal());
}
}

View File

@ -5,6 +5,7 @@ import ink.wgink.module.file.pojo.vos.filedownload.FileDownloadVO;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
@ -66,4 +67,13 @@ public interface IFileDownloadService {
*/
Integer countByFileId(String fileId);
/**
* 下载
*
* @param httpServletRequest
* @param isOpen 是否打开
* @param fileId
*/
void handle(HttpServletRequest httpServletRequest, boolean isOpen, String fileId);
}

View File

@ -12,9 +12,13 @@ import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.date.DateUtil;
import ink.wgink.util.map.HashMapUtil;
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.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
@ -73,5 +77,16 @@ public class FileDownloadServiceImpl extends DefaultBaseService implements IFile
return fileDownloadDao.count(params);
}
@Override
public void handle(HttpServletRequest httpServletRequest, boolean isOpen, String fileId) {
String requestIp = RequestUtil.getRequestIp(httpServletRequest);
if (!isOpen && !StringUtils.isBlank(requestIp)) {
// 记录下载历史
CachedThreadPoolUtil.execute(() -> {
save(new FileDownloadVO(fileId, requestIp));
});
}
}
}

View File

@ -25,6 +25,9 @@ import java.util.Map;
*/
public interface IFileService {
String FILE_SUMMARY_LOCAL = "local";
String FILE_SUMMARY_CENTER = "center";
/**
* 单文件上传
*
@ -151,4 +154,14 @@ public interface IFileService {
*/
SuccessResultList<List<FileInfoDTO>> listPage(ListPage page);
/**
* 获取文件保存VO
*
* @param inputStream
* @param uploadTypeEnum
* @param fileName
* @return
*/
FileSaveVO getCenterFileSaveVO(InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName, String creator);
}

View File

@ -3,6 +3,7 @@ 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.rpc.rest.pojo.RemoteFileInputStream;
import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.module.file.components.FileComponent;
@ -11,18 +12,19 @@ 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.vos.filedownload.FileDownloadVO;
import ink.wgink.module.file.pojo.vos.v2.FileSaveVO;
import ink.wgink.module.file.pojo.vos.v2.FileUpdateVO;
import ink.wgink.module.file.remote.IFileCenterRemoteService;
import ink.wgink.module.file.service.filedownload.IFileDownloadService;
import ink.wgink.module.file.service.v2.IFileService;
import ink.wgink.module.file.utils.FileUtil;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.pos.FilePO;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.properties.FileCenterProperties;
import ink.wgink.properties.FileProperties;
import ink.wgink.util.UUIDUtil;
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.stereotype.Service;
@ -48,67 +50,65 @@ import java.util.Map;
@Service("fileServiceV2")
public class FileServiceImpl extends DefaultBaseService implements IFileService {
@Autowired
private FileProperties fileProperties;
@Autowired
private FileComponent fileComponent;
@Autowired
private IFileDao fileDao;
@Autowired
private IFileDownloadService fileDownloadService;
@Autowired
private IFileCenterRemoteService fileUploadCenterService;
@Override
public FileUploadSuccessDTO uploadSingle(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
FileSaveVO fileSaveVO = getFileSaveVO(uploadFile, uploadTypeEnum);
fileSaveVO.setCreator(securityComponent.getCurrentUser().getUserId());
FileSaveVO fileSaveVO = getCenterFileSaveVO(uploadFile, uploadTypeEnum, securityComponent.getCurrentUser().getUserId());
return saveFile(fileSaveVO);
}
@Override
public FileUploadSuccessDTO uploadSingle(InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName) {
FileSaveVO fileSaveVO = getFileSaveVO(inputStream, uploadTypeEnum, fileName);
fileSaveVO.setCreator(securityComponent.getCurrentUser().getUserId());
FileSaveVO fileSaveVO = getCenterFileSaveVO(inputStream, uploadTypeEnum, fileName, securityComponent.getCurrentUser().getUserId());
return saveFile(fileSaveVO);
}
@Override
public FileUploadSuccessDTO uploadSingleByToken(String token, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
FileSaveVO fileSaveVO = getFileSaveVO(uploadFile, uploadTypeEnum);
fileSaveVO.setCreator(getAppTokenUser(token).getId());
FileSaveVO fileSaveVO = getCenterFileSaveVO(uploadFile, uploadTypeEnum, getAppTokenUser(token).getId());
return saveFile(fileSaveVO);
}
@Override
public FileUploadSuccessDTO uploadSingleByToken(String token, InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName) {
FileSaveVO fileSaveVO = getFileSaveVO(inputStream, uploadTypeEnum, fileName);
fileSaveVO.setCreator(getAppTokenUser(token).getId());
FileSaveVO fileSaveVO = getCenterFileSaveVO(inputStream, uploadTypeEnum, fileName, getAppTokenUser(token).getId());
return saveFile(fileSaveVO);
}
@Override
public FileUploadSuccessDTO uploadSingleByUserId(String userId, MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
FileSaveVO fileSaveVO = getFileSaveVO(uploadFile, uploadTypeEnum);
fileSaveVO.setCreator(userId);
FileSaveVO fileSaveVO = getCenterFileSaveVO(uploadFile, uploadTypeEnum, userId);
return saveFile(fileSaveVO);
}
@Override
public FileUploadSuccessDTO uploadSingleByUserId(String userId, InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName) {
FileSaveVO fileSaveVO = getFileSaveVO(inputStream, uploadTypeEnum, fileName);
fileSaveVO.setCreator(userId);
FileSaveVO fileSaveVO = getCenterFileSaveVO(inputStream, uploadTypeEnum, fileName, userId);
return saveFile(fileSaveVO);
}
@Override
public FileUploadSuccessDTO saveFile(FileSaveVO fileSaveVO) {
String fileUrl = fileComponent.getFileUrl(fileSaveVO.getUploadPath());
String fileId = UUIDUtil.getUUID();
Map<String, Object> params = getHashMap(10);
params.put("fileId", fileId);
params.put("fileName", fileSaveVO.getFileName());
params.put("filePath", fileSaveVO.getUploadPath());
params.put("fileUrl", fileUrl);
params.put("fileUrl", fileSaveVO.getFileUrl());
params.put("fileType", fileSaveVO.getFileType());
params.put("fileSize", fileSaveVO.getFileSize());
params.put("fileSummary", fileSaveVO.getFileSummary());
params.put("isBack", 0);
String time = DateUtil.getTime();
@ -119,7 +119,7 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
params.put("isDelete", 0);
fileDao.save(params);
return new FileUploadSuccessDTO(fileId, fileSaveVO.getFileName(), fileSaveVO.getFileSize(), fileUrl);
return new FileUploadSuccessDTO(fileId, fileSaveVO.getFileName(), fileSaveVO.getFileSize(), fileSaveVO.getFileUrl());
}
@Override
@ -179,16 +179,9 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
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);
});
}
fileDownloadService.handle(request, isOpen, fileId);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -212,6 +205,24 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
return new SuccessResultList<>(fileInfoDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
}
@Override
public FileSaveVO getCenterFileSaveVO(InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName, String creator) {
String fileType = fileComponent.getFileType(fileName);
String uploadPath = fileComponent.getUploadPath(uploadTypeEnum, fileType);
String uuidFileName = UUIDUtil.get32UUID() + "." + fileType;
long fileSize = FileUtil.save(inputStream, uuidFileName, uploadPath);
// 保存文件
FileSaveVO fileSaveVO = new FileSaveVO();
fileSaveVO.setFileName(fileName);
fileSaveVO.setFileType(fileType);
fileSaveVO.setUploadPath(uploadPath + File.separator + uuidFileName);
fileSaveVO.setFileUrl(fileComponent.getFileUrl(fileSaveVO.getUploadPath()));
fileSaveVO.setFileSize(fileSize);
fileSaveVO.setCreator(creator);
fileSaveVO.setFileSummary(FILE_SUMMARY_LOCAL);
return fileSaveVO;
}
/**
* 设置查询文件类型
*
@ -256,7 +267,7 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
* @param uploadTypeEnum
* @return
*/
private FileSaveVO getFileSaveVO(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum) {
private FileSaveVO getCenterFileSaveVO(MultipartFile uploadFile, UploadTypeEnum uploadTypeEnum, String creator) {
String fileName = uploadFile.getOriginalFilename();
InputStream inputStream;
try {
@ -264,28 +275,66 @@ public class FileServiceImpl extends DefaultBaseService implements IFileService
} catch (IOException e) {
throw new SearchException(e);
}
return getFileSaveVO(inputStream, uploadTypeEnum, fileName);
// 上传到文件中心
if (fileProperties.getCenter() != null) {
return getCenterFileSaveVO(inputStream, uploadTypeEnum, fileName, uploadFile.getSize(), creator);
}
return getCenterFileSaveVO(inputStream, uploadTypeEnum, fileName, creator);
}
/**
* 获取文件保存VO
* 上传文件到文件中心
*
* @param inputStream
* @param uploadTypeEnum
* @param fileName
* @param fileSize
* @param creator
* @return
*/
private FileSaveVO getFileSaveVO(InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName) {
private FileSaveVO getCenterFileSaveVO(InputStream inputStream, UploadTypeEnum uploadTypeEnum, String fileName, long fileSize, String creator) {
RemoteFileInputStream remoteFileInputStream = new RemoteFileInputStream();
remoteFileInputStream.setInputStream(inputStream);
remoteFileInputStream.setFileName(fileName);
remoteFileInputStream.setFileSize(fileSize);
String fileType = fileComponent.getFileType(fileName);
String uploadPath = fileComponent.getUploadPath(uploadTypeEnum, fileType);
String uuidFileName = UUIDUtil.get32UUID() + "." + fileType;
long fileSize = fileComponent.saveFile(inputStream, uuidFileName, uploadPath);
// 保存文件
FileCenterProperties fileCenterProperties = fileProperties.getCenter();
FileUploadSuccessDTO fileUploadSuccessDTO;
if (UploadTypeEnum.IMAGE.equals(uploadTypeEnum)) {
fileUploadSuccessDTO = fileUploadCenterService.uploadImage(fileCenterProperties.getUploadUrl(),
fileCenterProperties.getAccessKey(),
fileCenterProperties.getAccessSecret(),
remoteFileInputStream,
creator);
} else if (UploadTypeEnum.VIDEO.equals(uploadTypeEnum)) {
fileUploadSuccessDTO = fileUploadCenterService.uploadVideo(fileCenterProperties.getUploadUrl(),
fileCenterProperties.getAccessKey(),
fileCenterProperties.getAccessSecret(),
remoteFileInputStream,
creator);
} else if (UploadTypeEnum.AUDIO.equals(uploadTypeEnum)) {
fileUploadSuccessDTO = fileUploadCenterService.uploadAudio(fileCenterProperties.getUploadUrl(),
fileCenterProperties.getAccessKey(),
fileCenterProperties.getAccessSecret(),
remoteFileInputStream,
creator);
} else {
fileUploadSuccessDTO = fileUploadCenterService.uploadFile(fileCenterProperties.getUploadUrl(),
fileCenterProperties.getAccessKey(),
fileCenterProperties.getAccessSecret(),
remoteFileInputStream,
creator);
}
FileSaveVO fileSaveVO = new FileSaveVO();
fileSaveVO.setFileName(fileName);
fileSaveVO.setUploadPath(fileCenterProperties.getUploadUrl());
fileSaveVO.setFileUrl(fileUploadSuccessDTO.getFileUrl());
fileSaveVO.setFileType(fileType);
fileSaveVO.setUploadPath(uploadPath + File.separator + uuidFileName);
fileSaveVO.setFileSize(fileSize);
fileSaveVO.setFileName(fileName);
fileSaveVO.setCreator(creator);
fileSaveVO.setFileSummary(FILE_SUMMARY_CENTER);
return fileSaveVO;
}

View File

@ -1,6 +1,8 @@
package ink.wgink.module.file.startup;
import ink.wgink.interfaces.manager.IFilesShowCodeService;
import ink.wgink.module.file.dao.fileclient.IFileClientDao;
import ink.wgink.module.file.manager.FileRemoteManager;
import ink.wgink.module.file.manager.FilesManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
@ -20,10 +22,13 @@ public class FilesStartUp implements ApplicationRunner {
@Autowired
private IFilesShowCodeService filesShowCodeService;
@Autowired
private IFileClientDao fileRemoteDao;
@Override
public void run(ApplicationArguments args) throws Exception {
FilesManager.getInstance().setFilesShowCodeService(filesShowCodeService);
FileRemoteManager.getInstance().setFileRemoteDao(fileRemoteDao);
}
@Scheduled(cron = "0 0/1 * * * ?")

View File

@ -0,0 +1,119 @@
package ink.wgink.module.file.utils;
import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.module.file.service.IFileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @ClassName: FileSaveUtil
* @Description: 保存文件工具
* @Author: wanggeng
* @Date: 2022/8/3 21:12
* @Version: 1.0
*/
public class FileUtil {
private static final Logger LOG = LoggerFactory.getLogger(FileUtil.class);
private static final char[] HEX_CODE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* 保存文件
*
* @param fileInputStream 文件流
* @param fileName 文件名
* @param filePath 保存路径
* @return 文件大小
*/
public static long save(InputStream fileInputStream, String fileName, String filePath) {
File uploadFolder = new File(filePath);
if (!uploadFolder.exists()) {
uploadFolder.mkdirs();
}
FileOutputStream uploadFileOutputStream = null;
long fileSize = 0;
try {
uploadFileOutputStream = new FileOutputStream(uploadFolder + File.separator + fileName);
int readLength;
for (byte[] buf = new byte[IFileService.INPUT_STREAM_SIZE]; (readLength = fileInputStream.read(buf)) > -1; ) {
uploadFileOutputStream.write(buf, 0, readLength);
fileSize += readLength;
}
uploadFileOutputStream.flush();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new FileException("文件上传失败");
} finally {
try {
if (null != uploadFileOutputStream) {
uploadFileOutputStream.close();
}
if (null != fileInputStream) {
fileInputStream.close();
}
} catch (Exception e1) {
LOG.error(e1.getMessage());
throw new FileException("文件上传失败");
}
}
return fileSize;
}
/**
* 删除源文件
*
* @param sourceFilePath
*/
public static boolean delete(String sourceFilePath) {
File file = new File(sourceFilePath);
if (file.exists()) {
return file.delete();
}
return true;
}
/**
* 获取文件的MD5
*
* @param file
* @return
*/
public static String getMD5(File file) {
if (file == null) {
throw new SearchException("文件不存在");
}
if (!file.exists()) {
throw new SearchException("文件不存在");
}
String fileMd5;
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
int readLength;
for (byte[] buf = new byte[IFileService.INPUT_STREAM_SIZE]; (readLength = inputStream.read(buf)) > -1; ) {
messageDigest.update(buf, 0, readLength);
}
// 计算文件的MD5
byte[] data = messageDigest.digest();
StringBuilder fileMd5SB = new StringBuilder(data.length * 2);
for (byte b : data) {
fileMd5SB.append(HEX_CODE[(b >> 4) & 0xF]);
fileMd5SB.append(HEX_CODE[(b & 0xF)]);
}
fileMd5 = fileMd5SB.toString();
} catch (IOException | NoSuchAlgorithmException e) {
throw new SystemException(e);
}
return fileMd5;
}
}

View File

@ -0,0 +1,116 @@
<?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.fileclient.IFileClientDao">
<resultMap id="fileClientDTO" type="ink.wgink.module.file.pojo.dtos.fileclient.FileClientDTO">
<id property="fileClientId" column="file_client_id"/>
<result property="accessKey" column="access_key"/>
<result property="accessSecret" column="access_secret"/>
<result property="status" column="status"/>
<result property="gmtCreate" column="gmt_create"/>
</resultMap>
<!-- 建表 -->
<update id="createTable">
CREATE TABLE IF NOT EXISTS `sys_file_client` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`file_client_id` char(36) DEFAULT NULL COMMENT '主键',
`title` varchar(255) DEFAULT NULL COMMENT '标题',
`access_key` varchar(255) DEFAULT NULL COMMENT '上传Key',
`access_secret` varchar(255) DEFAULT NULL COMMENT '上传密码',
`status` varchar(255) DEFAULT NULL COMMENT '状态',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`creator` char(36) DEFAULT NULL COMMENT '创建人',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
`modifier` char(36) DEFAULT NULL COMMENT '修改人',
`is_delete` int(1) DEFAULT '0' COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `file_client_id` (`file_client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件远程调用';
</update>
<!-- 保存文件 -->
<insert id="save" parameterType="map">
INSERT INTO sys_file_client (
file_client_id,
title,
access_key,
access_secret,
status,
gmt_create,
creator,
gmt_modified,
modifier,
is_delete
) VALUES(
#{fileClientId},
#{title},
#{accessKey},
#{accessSecret},
#{status},
#{gmtCreate},
#{creator},
#{gmtModified},
#{modifier},
#{isDelete}
)
</insert>
<!-- 删除 -->
<update id="remove" parameterType="map">
UPDATE
sys_file_client
SET
gmt_modified = #{gmtModified},
modifier = #{modifier},
is_delete = 0
</update>
<!-- 修改状态 -->
<update id="update" parameterType="map">
UPDATE
sys_file_client
SET
title = #{title},
status = #{status},
gmt_modified = #{gmtModified},
modifier = #{modifier}
WHERE
file_client_id = #{fileClientId}
</update>
<!-- 文件列表 -->
<select id="get" parameterType="map" resultMap="fileClientDTO">
SELECT
file_client_id,
title,
access_key,
access_secret,
status,
gmt_create
FROM
sys_file_client
WHERE
file_client_id = #{fileClientId}
</select>
<!-- 文件列表 -->
<select id="list" parameterType="map" resultMap="fileClientDTO">
SELECT
file_client_id,
title,
access_key,
access_secret,
status,
gmt_create
FROM
sys_file_client
WHERE
is_delete = 0
<if test="status != null and status != ''">
AND
status = #{status}
</if>
</select>
</mapper>

View File

@ -0,0 +1,253 @@
<!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>
<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-sm" lay-event="saveEvent">
<i class="fa fa-lg fa-plus"></i> 新增
</button>
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" lay-event="updateEvent">
<i class="fa fa-lg fa-edit"></i> 编辑
</button>
<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-client/listpage';
// 初始化表格
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: 'title', width: 200, title: '标题', align: 'center',
templet: function (row) {
var rowData = row[this.field];
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field: 'accessKey', width: 180, title: 'Key', align: 'center',
templet: function (row) {
var rowData = row[this.field];
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field: 'accessSecret', width: 180, title: 'Secret', align: 'center',
templet: function (row) {
var rowData = row[this.field];
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
return rowData;
}
},
{field: 'status', width: 100, title: '状态', align: 'center',
templet: function (row) {
var rowData = row[this.field];
if (typeof (rowData) === 'undefined' || rowData == null || rowData == '') {
return '-';
}
if(rowData === 'active') {
return '已激活';
}
if(rowData === 'inactive') {
return '未激活';
}
return '错误';
}
},
{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);
});
// 删除
function removeData(ids) {
top.dialog.msg(top.dataMessage.delete, {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function (index) {
top.dialog.close(index);
var layIndex;
top.restAjax.delete(top.restAjax.path('api/file-remote/remove/{ids}', [ids]), {}, null, function (code, data) {
top.dialog.msg(top.dataMessage.deleteSuccess, {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);
});
}
});
}
// 事件 - 增删改
table.on('toolbar(dataTable)', function(obj) {
var layEvent = obj.event;
var checkStatus = table.checkStatus('dataTable');
var checkDatas = checkStatus.data;
if(layEvent === 'saveEvent') {
layer.open({
type: 2,
title: false,
closeBtn: 0,
area: ['100%', '100%'],
shadeClose: true,
anim: 2,
content: top.restAjax.path('route/file-remote/save', []),
end: function() {
reloadTable();
}
});
} else if(layEvent === 'updateEvent') {
if(checkDatas.length === 0) {
top.dialog.msg(top.dataMessage.table.selectEdit);
} else if(checkDatas.length > 1) {
top.dialog.msg(top.dataMessage.table.selectOneEdit);
} else {
layer.open({
type: 2,
title: false,
closeBtn: 0,
area: ['100%', '100%'],
shadeClose: true,
anim: 2,
content: top.restAjax.path('route/file-remote/update?fileRemoteId={fileRemoteId}', [checkDatas[0].fileRemoteId]),
end: function() {
reloadTable();
}
});
}
} else 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['fileRemoteId'];
}
removeData(ids);
}
}
});
})
</script>
</body>
</html>

View File

@ -0,0 +1,108 @@
<!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">
</head>
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb" lay-filter="breadcrumb" style="visibility: visible;">
<a class="close" href="javascript:void(0);">上级列表</a><span lay-separator="">/</span>
<a href="javascript:void(0);"><cite>新增内容</cite></a>
</span>
</div>
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" id="title" name="title" class="layui-input" value="" placeholder="请输入标题" lay-verify="required">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<input type="radio" name="status" value="active" title="激活" checked>
<input type="radio" name="status" value="inactive" title="未激活">
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="layui-footer" style="left: 0;">
<button type="button" class="layui-btn" lay-submit lay-filter="submitForm">提交新增</button>
<button type="button" class="layui-btn layui-btn-primary close">返回上级</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'form', 'laydate', 'laytpl'], function(){
var $ = layui.$;
var form = layui.form;
var laytpl = layui.laytpl;
var laydate = layui.laydate;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 初始化内容
function initData() {}
initData();
// 提交表单
form.on('submit(submitForm)', function(formData) {
top.dialog.confirm(top.dataMessage.commit, function(index) {
top.dialog.close(index);
var loadLayerIndex;
top.restAjax.post(top.restAjax.path('api/file-client/save', []), formData.field, null, function(code, data) {
var layerIndex = top.dialog.msg(top.dataMessage.commitSuccess, {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function(index) {
top.dialog.close(index);
window.location.reload();
},
btn2: function() {
closeBox();
}
});
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.committing, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
});
return false;
});
$('.close').on('click', function() {
closeBox();
});
// 校验
form.verify({
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,125 @@
<!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">
</head>
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb" lay-filter="breadcrumb" style="visibility: visible;">
<a class="close" href="javascript:void(0);">上级列表</a><span lay-separator="">/</span>
<a href="javascript:void(0);"><cite>编辑内容</cite></a>
</span>
</div>
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form layui-form-pane" lay-filter="dataForm">
<div class="layui-form-item">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" id="title" name="title" class="layui-input" value="" placeholder="请输入标题" lay-verify="required">
</div>
</div>
<div class="layui-form-item" pane>
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<input type="radio" name="status" value="active" title="激活" checked>
<input type="radio" name="status" value="inactive" title="未激活">
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="layui-footer" style="left: 0;">
<button type="button" class="layui-btn" lay-submit lay-filter="submitForm">提交编辑</button>
<button type="button" class="layui-btn layui-btn-primary close">返回上级</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'form', 'laydate', 'laytpl'], function(){
var $ = layui.$;
var form = layui.form;
var laytpl = layui.laytpl;
var laydate = layui.laydate;
var fileRemoteId = top.restAjax.params(window.location.href).fileRemoteId;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 初始化内容
function initData() {
var loadLayerIndex;
top.restAjax.get(top.restAjax.path('api/file-client/get/{fileRemoteId}', [fileRemoteId]), {}, null, function(code, data) {
var dataFormData = {};
for(var i in data) {
dataFormData[i] = data[i];
}
form.val('dataForm', dataFormData);
form.render(null, 'dataForm');
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
}
initData();
// 提交表单
form.on('submit(submitForm)', function(formData) {
top.dialog.confirm(top.dataMessage.commit, function(index) {
top.dialog.close(index);
var loadLayerIndex;
top.restAjax.put(top.restAjax.path('api/file-client/update/{fileRemoteId}', [fileRemoteId]), formData.field, null, function(code, data) {
var layerIndex = top.dialog.msg(top.dataMessage.updateSuccess, {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function(index) {
top.dialog.close(index);
window.location.reload();
},
btn2: function() {
closeBox();
}
});
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.committing, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
});
return false;
});
$('.close').on('click', function() {
closeBox();
});
// 校验
form.verify({
});
});
</script>
</body>
</html>