开发临时文件上传功能,todo 未完成

master
土豆兄弟 4 years ago
parent 7297bfa9e3
commit 2f8b923ae3

33
.gitignore vendored

@ -3,3 +3,36 @@
*.iml *.iml
*/target/* */target/*
*/*.iml */*.iml
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

@ -0,0 +1,97 @@
package me.zhengjie.common.http;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.io.Serializable;
//属性为 空("" 或者为 NULL 都不序列化则返回的json是没有这个字段的。这样对移动端会更省流量
@JsonSerialize
@Getter // 设置get方法
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@NoArgsConstructor
public class CommonResponse<T> implements Serializable {
// 成功还是失败的状态标识 0,成功 1,失败
private int status;
// 返回信息
private String msg;
// 返回的结果数据
private T data;
/*
*/
private CommonResponse(int status) {
this.status = status;
}
private CommonResponse(int status, T data) { // ps: 当调用T为String类型时候,会默认调用下面的ServerResponse(int status, String msg)类型的构造器
this.status = status;
this.data = data;
}
private CommonResponse(int status, String msg, T data) {
this.status = status;
this.msg = msg;
this.data = data;
}
private CommonResponse(int status, String msg) {
this.status = status;
this.msg = msg;
}
/*
,,
*/
//返回成功码和默认的成功信息
public static <T> CommonResponse<T> createBySuccess() {
return new CommonResponse<T>(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getDesc());
}
//返回成功码和成功信息
public static <T> CommonResponse<T> createBySuccessMessage(String msg) {
return new CommonResponse<T>(ResponseCode.SUCCESS.getCode(), msg);
}
//返回成功码和数据
public static <T> CommonResponse<T> createBySuccess(T data) {
return new CommonResponse<T>(ResponseCode.SUCCESS.getCode(), data);
}
//返回错误码和错误描述
public static <T> CommonResponse<T> createBySuccessByCode(ResponseCode responseCode){
return new CommonResponse<T>(responseCode.getCode(),responseCode.getDesc());
}
//返回成功码和成功信息和数据
public static <T> CommonResponse<T> createBySuccess(String msg, T data) {
return new CommonResponse<T>(ResponseCode.SUCCESS.getCode(), msg, data);
}
/*
,,
*/
//返回错误码和错误描述
public static <T> CommonResponse<T> createByError(ResponseCode responseCode){
return new CommonResponse<T>(responseCode.getCode(),responseCode.getDesc());
}
//返回错误码和错误信息(传入)
public static <T> CommonResponse<T> createByErrorMessage(String errorMessage){
return new CommonResponse<T>(ResponseCode.ERROR.getCode(),errorMessage);
}
//返回错误码(传入)和错误信息(传入)
public static <T> CommonResponse<T> createByErrorCodeMessage(int errorCode, String errorMessage){
return new CommonResponse<T>(errorCode,errorMessage);
}
}

@ -0,0 +1,49 @@
package me.zhengjie.common.http;
/**
* FileName: ResponseCode
* Author: x
* Date: 2019/12/11 20:30
* Description: Response ->
* History:
* <author> <time> <version> <desc>
* x 2019/12/11 v 1.0
*/
public enum ResponseCode {
SUCCESS(0,"SUCCESS"),
ERROR(1,"ERROR"),
// 成功的一些特殊提示
SUCCESS_ONCE_LINK_MSG(0,"下载成功,一次性链接已经失效"),
// 通用请求参数校验
ILLEGAL_ARGUMENT(1,"请求参数格式错误"),
EMPTY_ARGUMENT(1,"请求参数为空"),
NO_MATCH_ARGUMENT_SET(1,"不能满足要求的参数设置"),
NO_FILE_INPUT(1,"没有文件输入"),
// 特殊需要进行前端返回说明的参数定义
TASK_NAME_IS_EXIST(1,"任务名称已经存在"),
ONCE_LINK_MSG_ERROR(1,"链接失效,下载文件失败~"),
// 请求结果性的错误
NODATA_ERROR(1,"查询结果为空"),
TASK_BUILD_ERROR(1,"任务建立失败"),
NO_RELEVANT_CONTENT_WAS_FOUND(1,"未查询到相关内容"),
DECRYPT_ERROR(1,"解密错误,请联系我");
private final int code;
private final String desc;
ResponseCode(int code, String desc){
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}

@ -0,0 +1,23 @@
package me.zhengjie.common.json;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* Json
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OnceLinkMsgJsonContent implements Serializable {
/**
*
*/
private String onceLink;
}

@ -0,0 +1,45 @@
package me.zhengjie.common.json;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Json -
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PushDBJsonContent {
/**
* id
*/
private Long actId;
/**
*
*/
private String actName;
/**
*
*/
private List<Client> clientList;
/**
*
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Client{
/**
*
*/
private String cellphone;
}
}

@ -0,0 +1,42 @@
package me.zhengjie.utils;
/**
*
*
*/
public class ConvertUtil {
/**
*
* , ""
*
*
* @param second
* @return
*/
public static String secondToTime(long second){
if (second <= 0){
return "";
}else {
second = second /1000; // 毫秒数转成秒数
}
long days = second / 86400; //转换天数
second = second % 86400; //剩余秒数
long hours = second / 3600; //转换小时
second = second % 3600; //剩余秒数
long minutes = second /60; //转换分钟
second = second % 60; //剩余秒数
if(days>0){
return days + "天" + hours + "小时" + minutes + "分" + second + "秒";
} else if (hours > 0 ){
return hours + "小时" + minutes + "分" + second + "秒";
} else if (minutes > 0){
return minutes + "分" + second + "秒";
}else if (second > 0){
return second + "秒";
}else {
return "";
}
}
}

@ -0,0 +1,52 @@
package me.zhengjie.config.thread;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
/**
* 线,线
*/
@Configuration
@EnableAsync
public class ThreadPoolConfig {
/**
* 线
*/
/**
* produce
*/
@Value(value = "${save.task.thread_pool.corePoolSize}")
private int saveCorePoolSize = 2;
@Value(value = "${save.task.thread_pool.maxPoolSize}")
private int saveMaxPoolSize = 16;
@Value(value = "${save.task.thread_pool.queueCapacity}")
private int saveQueueCapacity = 3;
@Value(value = "${save.task.thread_pool.ThreadNamePrefix}")
private String saveThreadNamePrefix = "SaveToFileTaskExecutor-"; // fixme 这个属性暂时没用起来
@Bean(value = "SendBigDataTaskExecutor")
public Executor SendBigDataTaskExecutor(){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
saveCorePoolSize,
saveMaxPoolSize,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(saveQueueCapacity),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
return threadPoolExecutor;
}
}

@ -0,0 +1,22 @@
package me.zhengjie.modules.upload.consts;
/**
*
*/
public class UploadFileConst {
/**
* ext -
*/
public static final String FILE_SPLIT = ".";
/**
*
*/
public static final String FILE_PATH_SPLIT = ",";
/**
*
*/
public static final Integer DOING_TAG = 1;
}

@ -0,0 +1,71 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.domain;
import lombok.Data;
import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.copier.CopyOptions;
import javax.persistence.*;
import javax.validation.constraints.*;
import java.sql.Timestamp;
import java.io.Serializable;
/**
* @website https://el-admin.vip
* @description /
* @author x
* @date 2021-01-03
**/
@Entity
@Data
@Table(name="tb_upload_file")
public class UploadFile implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@ApiModelProperty(value = "主键")
private Long id;
@Column(name = "upload_time")
@ApiModelProperty(value = "上传日期")
private Timestamp uploadTime;
@Column(name = "opration")
@ApiModelProperty(value = "操作人")
private String opration;
@Column(name = "file_count")
@ApiModelProperty(value = "文件解析总数")
private Long fileCount;
@Column(name = "file_trans_success_count")
@ApiModelProperty(value = "上传成功总数")
private Long fileTransSuccessCount;
@Column(name = "upload_tag")
@ApiModelProperty(value = "上传状态")
private Integer uploadTag;
@Column(name = "lcoal_save_path")
@ApiModelProperty(value = "文件上传保存路径")
private String localSavePath;
public void copy(UploadFile source){
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
}
}

@ -0,0 +1,28 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.repository;
import me.zhengjie.modules.upload.domain.UploadFile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @website https://el-admin.vip
* @author x
* @date 2021-01-03
**/
public interface UploadFileRepository extends JpaRepository<UploadFile, Long>, JpaSpecificationExecutor<UploadFile> {
}

@ -0,0 +1,111 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.rest;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.annotation.Log;
import me.zhengjie.common.http.CommonResponse;
import me.zhengjie.common.http.ResponseCode;
import me.zhengjie.modules.upload.domain.UploadFile;
import me.zhengjie.modules.upload.service.UploadFileService;
import me.zhengjie.modules.upload.service.dto.UploadFileQueryCriteria;
import org.springframework.data.domain.Pageable;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
/**
* @website https://el-admin.vip
* @author x
* @date 2021-01-03
**/
@RestController
@RequiredArgsConstructor
@Api(tags = "上传文件解析发送管理")
@RequestMapping("/api/uploadFile")
public class UploadFileController {
private final UploadFileService uploadFileService;
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('uploadFile:list')")
public void download(HttpServletResponse response, UploadFileQueryCriteria criteria) throws IOException {
uploadFileService.download(uploadFileService.queryAll(criteria), response);
}
@GetMapping
@Log("查询上传文件解析发送")
@ApiOperation("查询上传文件解析发送")
@PreAuthorize("@el.check('uploadFile:list')")
public ResponseEntity<Object> query(UploadFileQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(uploadFileService.queryAll(criteria,pageable),HttpStatus.OK);
}
@PostMapping
@Log("新增上传文件解析发送")
@ApiOperation("新增上传文件解析发送")
@PreAuthorize("@el.check('uploadFile:add')")
public ResponseEntity<Object> create(@Validated @RequestBody UploadFile resources){
return new ResponseEntity<>(uploadFileService.create(resources),HttpStatus.CREATED);
}
@PutMapping
@Log("修改上传文件解析发送")
@ApiOperation("修改上传文件解析发送")
@PreAuthorize("@el.check('uploadFile:edit')")
public ResponseEntity<Object> update(@Validated @RequestBody UploadFile resources){
uploadFileService.update(resources);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@Log("删除上传文件解析发送")
@ApiOperation("删除上传文件解析发送")
@PreAuthorize("@el.check('uploadFile:del')")
@DeleteMapping
public ResponseEntity<Object> delete(@RequestBody Long[] ids) {
uploadFileService.deleteAll(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
// ==== 去重开发 =====
@Log("上传并加密任务")
@ApiOperation("上传并加密任务")
@PostMapping(value = "/sendTask")
@AnonymousAccess // fixme 需要测试完成后进行去除和使用上面的权限注解
public ResponseEntity<Object> sendTask(@RequestParam(value = "files") MultipartFile[] files) {
// 校验上传是否有文件
if (files!= null && files.length<= 0){
return new ResponseEntity<>(CommonResponse.createByError(ResponseCode.NO_FILE_INPUT), HttpStatus.OK);
}
// 生成本地文件
uploadFileService.encryptDataAndSaveToFile(files);
return new ResponseEntity<>(CommonResponse.createBySuccess(ResponseCode.SUCCESS), HttpStatus.OK);
}
}

@ -0,0 +1,92 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.service;
import me.zhengjie.modules.upload.domain.UploadFile;
import me.zhengjie.modules.upload.service.dto.UploadFileDto;
import me.zhengjie.modules.upload.service.dto.UploadFileQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
/**
* @website https://el-admin.vip
* @description
* @author x
* @date 2021-01-03
**/
public interface UploadFileService {
/**
*
* @param criteria
* @param pageable
* @return Map<String,Object>
*/
Map<String,Object> queryAll(UploadFileQueryCriteria criteria, Pageable pageable);
/**
*
* @param criteria
* @return List<UploadFileDto>
*/
List<UploadFileDto> queryAll(UploadFileQueryCriteria criteria);
/**
* ID
* @param id ID
* @return UploadFileDto
*/
UploadFileDto findById(Long id);
/**
*
* @param resources /
* @return UploadFileDto
*/
UploadFileDto create(UploadFile resources);
/**
*
* @param resources /
*/
void update(UploadFile resources);
/**
*
* @param ids /
*/
void deleteAll(Long[] ids);
/**
*
* @param all
* @param response /
* @throws IOException /
*/
void download(List<UploadFileDto> all, HttpServletResponse response) throws IOException;
/**
*
*
* @param files
*/
void encryptDataAndSaveToFile(MultipartFile[] files);
}

@ -0,0 +1,48 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.service.dto;
import lombok.Data;
import java.sql.Timestamp;
import java.io.Serializable;
/**
* @website https://el-admin.vip
* @description /
* @author x
* @date 2021-01-03
**/
@Data
public class UploadFileDto implements Serializable {
/** 主键 */
private Long id;
/** 上传日期 */
private Timestamp uploadTime;
/** 操作人 */
private String opration;
/** 文件解析总数 */
private Long fileCount;
/** 上传成功总数 */
private Long fileTransSuccessCount;
/** 上传状态 */
private Integer uploadTag;
}

@ -0,0 +1,46 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.service.dto;
import lombok.Data;
import java.sql.Timestamp;
import java.util.List;
import me.zhengjie.annotation.Query;
/**
* @website https://el-admin.vip
* @author x
* @date 2021-01-03
**/
@Data
public class UploadFileQueryCriteria{
/** 精确 */
@Query
private Long id;
/** 模糊 */
@Query(type = Query.Type.INNER_LIKE)
private String opration;
/** 精确 */
@Query
private Integer uploadTag;
/** BETWEEN */
@Query(type = Query.Type.BETWEEN)
private List<Timestamp> uploadTime;
}

@ -0,0 +1,227 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.service.impl;
import java.io.File;
import java.nio.file.Paths;
import java.sql.Timestamp;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.upload.domain.UploadFile;
import me.zhengjie.modules.upload.task.SaveToFileTask;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.upload.repository.UploadFileRepository;
import me.zhengjie.modules.upload.service.UploadFileService;
import me.zhengjie.modules.upload.service.dto.UploadFileDto;
import me.zhengjie.modules.upload.service.dto.UploadFileQueryCriteria;
import me.zhengjie.modules.upload.service.mapstruct.UploadFileMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import static me.zhengjie.modules.upload.consts.UploadFileConst.*;
/**
* @author x
* @website https://el-admin.vip
* @description
* @date 2021-01-03
**/
@Service
@RequiredArgsConstructor
@Slf4j
public class UploadFileServiceImpl implements UploadFileService {
/**
*
*/
@Value("${remote.link.address}")
private String remoteFileServerAddress;
/**
* - linux
*/
@Value("${remote.link.file-base-path-linux}")
private String remoteLinkFileBasePathLinux;
/**
* - linux
*/
@Value("${remote.link.file-base-path-windows}")
private String remoteLinkFileBasePathWindows;
/**
* - linux
*/
@Value("${remote.link.file-base-path-mac}")
private String remoteLinkFileBasePathMac;
private final UploadFileRepository uploadFileRepository;
private final UploadFileMapper uploadFileMapper;
@Autowired
private SaveToFileTask saveToFileTask;
@Override
public Map<String, Object> queryAll(UploadFileQueryCriteria criteria, Pageable pageable) {
Page<UploadFile> page = uploadFileRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
return PageUtil.toPage(page.map(uploadFileMapper::toDto));
}
@Override
public List<UploadFileDto> queryAll(UploadFileQueryCriteria criteria) {
return uploadFileMapper.toDto(uploadFileRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
}
@Override
@Transactional
public UploadFileDto findById(Long id) {
UploadFile uploadFile = uploadFileRepository.findById(id).orElseGet(UploadFile::new);
ValidationUtil.isNull(uploadFile.getId(), "UploadFile", "id", id);
return uploadFileMapper.toDto(uploadFile);
}
@Override
@Transactional(rollbackFor = Exception.class)
public UploadFileDto create(UploadFile resources) {
return uploadFileMapper.toDto(uploadFileRepository.save(resources));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(UploadFile resources) {
UploadFile uploadFile = uploadFileRepository.findById(resources.getId()).orElseGet(UploadFile::new);
ValidationUtil.isNull(uploadFile.getId(), "UploadFile", "id", resources.getId());
uploadFile.copy(resources);
uploadFileRepository.save(uploadFile);
}
@Override
public void deleteAll(Long[] ids) {
for (Long id : ids) {
uploadFileRepository.deleteById(id);
}
}
@Override
public void download(List<UploadFileDto> all, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (UploadFileDto uploadFile : all) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("上传日期", uploadFile.getUploadTime());
map.put("操作人", uploadFile.getOpration());
map.put("文件解析总数", uploadFile.getFileCount());
map.put("上传成功总数", uploadFile.getFileTransSuccessCount());
map.put("上传状态", uploadFile.getUploadTag());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
@Override
public void encryptDataAndSaveToFile(MultipartFile[] files) {
// 1. 文件存储到本地
long count = 0; // 统计总数
String baseStr = RandomUtil.randomString(11) + File.separator; // 生成通用随机文件夹存放每次的文件
StringBuilder pathBuilder = new StringBuilder();
for (MultipartFile file : files) {
// 获取原来的文件后缀
String originalFilename = file.getOriginalFilename();
if (StringUtils.isBlank(originalFilename)) {
log.error("===================== [input file name is empty, please check ]===================");
}
String extName = FileUtil.extName(originalFilename);
String eachFilePath = buildFileWritePath(baseStr, extName);
try {
// 把文件保存到本地路径
file.transferTo(Paths.get(eachFilePath));
} catch (IOException e) {
log.error("============== [transferTo file fail, path is {} ] ==============", eachFilePath);
}
// 统计行数
List<String> tempList = FileUtil.readLines(eachFilePath, "UTF-8");
if (CollectionUtil.isNotEmpty(tempList)){
count += tempList.size();
}
// 保存所有的临时存放路径
pathBuilder.append(eachFilePath);
pathBuilder.append(FILE_PATH_SPLIT);
}
// 2. 更新上传记录为正在上传,解析了有多少条
UploadFile uploadFile = new UploadFile();
uploadFile.setUploadTime(new Timestamp(new Date().getTime()));
uploadFile.setOpration("");//fixme 这边补充一下需要的操作人
uploadFile.setFileCount(count);
uploadFile.setFileTransSuccessCount(0L);
uploadFile.setUploadTag(DOING_TAG);
String tempFilesPath = pathBuilder.toString().substring(0, pathBuilder.length() - 1);
if (StringUtils.isNotBlank(tempFilesPath)){
uploadFile.setLocalSavePath(tempFilesPath); // 去掉最后的那个通配符 FILE_PATH_SPLIT
}
UploadFile save = uploadFileRepository.save(uploadFile);
// 2.1 如果临时生成失败就修改状态为失败
if (Objects.isNull(save)){
log.error("UploadFileServiceImpl:encryptDataAndSaveToFile | Operation Fail.UploadFile is Null");
}
// 3. 调用异步任务
saveToFileTask.doRunTask(tempFilesPath);
}
/**
*
*/
private String buildFileWritePath(String baseStr, String extName) {
// 获取环境配置信息
OsInfo osInfo = SystemUtil.getOsInfo();
// 生成一个随机文件夹目录,方便整理和打包
if (osInfo.isWindows()) {
FileUtil.mkdir(remoteLinkFileBasePathWindows + baseStr);
// 构建存储文件
return remoteLinkFileBasePathWindows + baseStr + RandomUtil.randomString(11) + FILE_SPLIT + extName;
} else if (osInfo.isLinux()) {
FileUtil.mkdir(remoteLinkFileBasePathLinux + baseStr);
// 构建存储文件
return remoteLinkFileBasePathLinux + baseStr + RandomUtil.randomString(11) + FILE_SPLIT + extName;
} else if (osInfo.isMac()) {
FileUtil.mkdir(remoteLinkFileBasePathMac + baseStr);
// 构建存储文件
return remoteLinkFileBasePathMac + baseStr + RandomUtil.randomString(11) + FILE_SPLIT + extName;
} else {
return "";
}
}
}

@ -0,0 +1,32 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.upload.service.mapstruct;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.upload.domain.UploadFile;
import me.zhengjie.modules.upload.service.dto.UploadFileDto;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @website https://el-admin.vip
* @author x
* @date 2021-01-03
**/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface UploadFileMapper extends BaseMapper<UploadFileDto, UploadFile> {
}

@ -0,0 +1,48 @@
package me.zhengjie.modules.upload.task;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.utils.ConvertUtil;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@Component
@Scope("prototype")
@Slf4j
public class SaveToFileTask {
@Async(value = "SendBigDataTaskExecutor")
public void doRunTask(String tempFilesPath){
Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
log.info("====== [ task start running, task name is {} ] ======", "SendBigDataTask");
runTask(tempFilesPath);
Long endMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
log.info("====== [ task start end, task name is {},cost milliSecond is {} ] ======", "SendBigDataTask", ConvertUtil.secondToTime(endMilliSecond - satrtMilliSecond));
}
/**
*
*
* @param tempFilesPath ,
*/
private void runTask(String tempFilesPath) {
// 4. 调用加密接口进行加密
// 4.1 失败进行容错
// 4.2 把临时存储的文件进行删除
// 4.3 更新状态为成功,更新解析成功的条数
// 5. 文件传输给2号库服务器
// 5.1 文件传输和记录更新()
}
}

@ -4,9 +4,9 @@ spring:
druid: druid:
db-type: com.alibaba.druid.pool.DruidDataSource db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false url: jdbc:log4jdbc:mysql://localhost:3306/eladmin-plat2?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root username: root
password: 123456 password: root
# 初始连接数 # 初始连接数
initial-size: 5 initial-size: 5
# 最小连接数 # 最小连接数
@ -111,3 +111,11 @@ file:
# 文件大小 /M # 文件大小 /M
maxSize: 100 maxSize: 100
avatarMaxSize: 5 avatarMaxSize: 5
# 线程池配置
save:
task:
thread_pool:
corePoolSize: 2
maxPoolSize: 16
queueCapacity: 3
ThreadNamePrefix: SaveToFileTaskExecutor-

@ -6,7 +6,7 @@ spring:
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false url: jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root username: root
password: 123456 password: Yuyou@2020
# 初始连接数 # 初始连接数
initial-size: 5 initial-size: 5
# 最小连接数 # 最小连接数

@ -53,3 +53,10 @@ code:
#密码加密传输,前端公钥加密,后端私钥解密 #密码加密传输,前端公钥加密,后端私钥解密
rsa: rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A== private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
# 设置项目的文件上传目录
remote:
link:
address: 'http://47.110.11.213:8000/api/temp/file/download'
file-base-path-linux: /home/eladmin/file/temp/
file-base-path-windows: C:\eladmin\file\temp\
file-base-path-mac: ~/file/eladmin/temp/

@ -1,45 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds" debug="false"> <configuration scan="true" scanPeriod="30 seconds" debug="false">
<contextName>elAdmin</contextName> <contextName>elAdmin</contextName>
<property name="log.charset" value="utf-8" /> <!-- 定义日志格式基础信息 -->
<property name="log.pattern" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)" /> <property name="LOG_DIR" value="./log/" />
<property name="LOG_PATTERN" value="%white(%contextName-) %d{yyyy-MM-dd HH:mm:ss:SS} %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{50}) - %cyan(%msg%n)" />
<property name="LOG_CHARSET" value="utf-8" />
<!--输出到控制台--> <!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="stdAppender" class="ch.qos.logback.core.ConsoleAppender">
<!--<withJansi>true</withJansi> &lt;!&ndash; 如果是UTF-8的环境这句要注释掉 &ndash;&gt;-->
<encoder> <encoder>
<pattern>${log.pattern}</pattern> <pattern>%highlight([%-5level]) %cyan(%d{yyyy-MM-dd#HH:mm:ss.SSS}) %yellow([Thread:%thread]) %magenta([Logger:%logger]) -> %msg%n</pattern>
<charset>${log.charset}</charset> <charset>utf-8</charset>
</encoder> </encoder>
</appender> </appender>
<!-- 输出到文件,并按天进行归档 -->
<appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/log.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天归档,如果按小时后面加-hh -->
<fileNamePattern>${LOG_DIR}/history/%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<append>true</append>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 不写TRACE DEBUG -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!--普通日志输出到控制台--> <!--普通日志输出到控制台-->
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
</root> </root>
<!--监控sql日志输出 --> <!--监控sql日志输出 -->
<logger name="jdbc.sqlonly" level="INFO" additivity="false"> <logger name="jdbc.sqlonly" level="INFO" additivity="false">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
<appender-ref ref="fileAppender"/>
</logger> </logger>
<logger name="jdbc.resultset" level="ERROR" additivity="false"> <logger name="jdbc.resultset" level="ERROR" additivity="false">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
<appender-ref ref="fileAppender"/>
</logger> </logger>
<!-- 如想看到表格数据将OFF改为INFO --> <!-- 如想看到表格数据将OFF改为INFO -->
<logger name="jdbc.resultsettable" level="OFF" additivity="false"> <logger name="jdbc.resultsettable" level="OFF" additivity="false">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
<appender-ref ref="fileAppender"/>
</logger> </logger>
<logger name="jdbc.connection" level="OFF" additivity="false"> <logger name="jdbc.connection" level="OFF" additivity="false">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
<appender-ref ref="fileAppender"/>
</logger> </logger>
<logger name="jdbc.sqltiming" level="OFF" additivity="false"> <logger name="jdbc.sqltiming" level="OFF" additivity="false">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
<appender-ref ref="fileAppender"/>
</logger> </logger>
<logger name="jdbc.audit" level="OFF" additivity="false"> <logger name="jdbc.audit" level="OFF" additivity="false">
<appender-ref ref="console" /> <appender-ref ref="stdAppender" />
<appender-ref ref="fileAppender"/>
</logger> </logger>
<root level="INFO">
<!-- TODO prod 环境去掉std -->
<appender-ref ref="stdAppender"/>
<!--<appender-ref ref="fileAppender"/>-->
</root>
</configuration> </configuration>
Loading…
Cancel
Save