!15 代码合并

Merge pull request !15 from MAC/develop
This commit is contained in:
MAC 2021-03-24 22:57:38 +08:00 committed by Gitee
commit 697f243a19
84 changed files with 1896 additions and 712 deletions

View File

@ -3,7 +3,7 @@
<a href="http://fileos.qiwenshare.com/"><img width="30%" src="https://images.gitee.com/uploads/images/2020/0810/131432_e00bbf82_947714.png" ></a>
</p>
<p align="center">
<strong>基于springboot + vue 框架开发的Web文件系统旨在为用户提供一个简单、方便的文件存储方案,能够以完善的目录结构体系,对文件进行管理 。</strong>
<strong>基于Spring Boot + VUE CLI@3 框架开发的分布式文件系统,旨在为用户和企业提供一个简单、方便的文件存储方案,能够以完善的目录结构体系,对文件进行管理 。</strong>
</p>
<p align="center">
<a target="_blank" href="https://baike.baidu.com/item/MIT%E8%AE%B8%E5%8F%AF%E8%AF%81/6671281?fr=aladdin">
@ -15,7 +15,6 @@
<a target="_blank" href="https://gitee.com/mingSoft/MCMS/stargazers">
<img src="https://gitee.com/qiwen-cloud/qiwen-file/badge/star.svg?theme=dark" alt='gitee star'/>
</a>
</p>
<p align="center">
<a href="http://pan.qiwenshare.com/" target="_blank">在线演示环境</a> &nbsp;|
@ -42,13 +41,24 @@
3. 支持对zip文件和rar文件的在线解压缩
4. 支持文件和目录的移动和复制
5. 多文件格式分类查看
6. 支持阿里云OSS对象存储
7. 增加分片上传该功能同时支持本地存储和阿里云OSS
6. 支持阿里云OSS对象存储,FastDFS存储
7. 增加分片上传该功能同时支持本地存储和阿里云OSS,FastDFS
8. 支持极速秒传功能,提高上传效率
9. 上传文件前台实时显示上传文件进度,上传速率,百分比等信息
10. 支持文件重命名
11. 可实时显示文件存储占用情况及总占用容量
12. ...
12. 支持ElasticSearch文件搜索
13. ...
## 项目代码地址
|系统|地址|
|-|-|
|奇文网盘前台|[https://gitee.com/qiwen-cloud/qiwen-file-web](https://gitee.com/qiwen-cloud/qiwen-file-web)|
|奇文网盘后台|[https://gitee.com/qiwen-cloud/qiwen-file](https://gitee.com/qiwen-cloud/qiwen-file)|
## 网络拓扑图
![输入图片说明](https://images.gitee.com/uploads/images/2021/0324/225520_d55b109e_947714.png "屏幕截图.png")
## 软件架构
该项目采用前后端分离的方式进行开发和部署,主要用到以下关键技术

View File

@ -43,18 +43,20 @@
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.csource</groupId>-->
<!-- <artifactId>fastdfs-client-java</artifactId>-->
<!-- <version>1.27-SNAPSHOT</version>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/net.oschina.zcx7878/fastdfs-client-java -->
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.config;
package com.qiwenshare.common.config;
import com.qiwenshare.common.domain.AliyunOSS;
import lombok.Data;

View File

@ -0,0 +1,14 @@
package com.qiwenshare.common.config;
import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;
@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FdfsConfig {
}

View File

@ -1,8 +1,7 @@
package com.qiwenshare.file.config;
package com.qiwenshare.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
@Data
@ -12,6 +11,9 @@ public class QiwenFileConfig {
private boolean shareMode;
private String storageType;
private String cacheMode;
private AliyunConfig aliyun = new AliyunConfig();
}

View File

@ -0,0 +1,37 @@
package com.qiwenshare.common.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class RedisAutoConfiguration extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
};
}
// @Bean
// public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
// .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
// return RedisCacheManager
// .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
// .cacheDefaults(redisCacheConfiguration).build();
// }
}

View File

@ -0,0 +1,9 @@
package com.qiwenshare.common.domain;
import lombok.Data;
@Data
public class DeleteFile {
private String fileUrl;
private String timeStampName;
}

View File

@ -0,0 +1,9 @@
package com.qiwenshare.common.domain;
import lombok.Data;
@Data
public class DownloadFile {
private String fileUrl;
private String timeStampName;
}

View File

@ -11,7 +11,9 @@ public class UploadFile {
private int success;
private String message;
private String url;
@Deprecated
private Integer isOSS;
private Integer storageType;
//切片上传相关参数
private String taskId;
private int chunkNumber;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.common.cbb;
package com.qiwenshare.common.exception;
public class NotSameFileExpection extends Exception {
public NotSameFileExpection() {

View File

@ -0,0 +1,12 @@
package com.qiwenshare.common.exception;
public abstract class UploadException extends RuntimeException{
protected UploadException(String message) {
super(message);
}
protected UploadException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,16 @@
package com.qiwenshare.common.exception;
public class UploadGeneralException extends UploadException{
public UploadGeneralException(Throwable cause) {
super("上传出现了异常", cause);
}
public UploadGeneralException(String message) {
super(message);
}
public UploadGeneralException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,39 @@
package com.qiwenshare.common.factory;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.operation.delete.product.AliyunOSSDeleter;
import com.qiwenshare.common.operation.download.Downloader;
import com.qiwenshare.common.operation.download.product.AliyunOSSDownloader;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.common.operation.upload.product.AliyunOSSUploader;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class AliyunOSSOperationFactory implements FileOperationFactory {
@Resource
AliyunOSSUploader aliyunOSSUploader;
@Resource
AliyunOSSDownloader aliyunOSSDownloader;
@Resource
AliyunOSSDeleter aliyunOSSDeleter;
@Override
public Uploader getUploader() {
return aliyunOSSUploader;
}
@Override
public Downloader getDownloader() {
return aliyunOSSDownloader;
}
@Override
public Deleter getDeleter() {
return aliyunOSSDeleter;
}
}

View File

@ -0,0 +1,38 @@
package com.qiwenshare.common.factory;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.operation.delete.product.FastDFSDeleter;
import com.qiwenshare.common.operation.download.Downloader;
import com.qiwenshare.common.operation.download.product.FastDFSDownloader;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.common.operation.upload.product.FastDFSUploader;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class FastDFSOperationFactory implements FileOperationFactory {
@Resource
FastDFSUploader fastDFSUploader;
@Resource
FastDFSDownloader fastDFSDownloader;
@Resource
FastDFSDeleter fastDFSDeleter;
@Override
public Uploader getUploader() {
return fastDFSUploader;
}
@Override
public Downloader getDownloader() {
return fastDFSDownloader;
}
@Override
public Deleter getDeleter() {
return fastDFSDeleter;
}
}

View File

@ -0,0 +1,11 @@
package com.qiwenshare.common.factory;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.operation.download.Downloader;
import com.qiwenshare.common.operation.upload.Uploader;
public interface FileOperationFactory {
Uploader getUploader();
Downloader getDownloader();
Deleter getDeleter();
}

View File

@ -0,0 +1,38 @@
package com.qiwenshare.common.factory;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.operation.delete.product.LocalStorageDeleter;
import com.qiwenshare.common.operation.download.Downloader;
import com.qiwenshare.common.operation.download.product.LocalStorageDownloader;
import com.qiwenshare.common.operation.upload.product.LocalStorageUploader;
import com.qiwenshare.common.operation.upload.Uploader;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class LocalStorageOperationFactory implements FileOperationFactory{
@Resource
LocalStorageUploader localStorageUploader;
@Resource
LocalStorageDownloader localStorageDownloader;
@Resource
LocalStorageDeleter localStorageDeleter;
@Override
public Uploader getUploader() {
return localStorageUploader;
}
@Override
public Downloader getDownloader() {
return localStorageDownloader;
}
@Override
public Deleter getDeleter() {
return localStorageDeleter;
}
}

View File

@ -278,9 +278,9 @@ public class FileOperation {
}
}
for (String zipPath : fileEntryNameList) {
if (FileUtil.isImageFile(FileUtil.getFileType(zipPath))) {
if (FileUtil.isImageFile(FileUtil.getFileExtendName(zipPath))) {
File file = new File(destDirPath + zipPath);
File minFile = new File(destDirPath + FileUtil.getFileNameNotExtend(zipPath) + "_min." + FileUtil.getFileType(zipPath));
File minFile = new File(destDirPath + FileUtil.getFileNameNotExtend(zipPath) + "_min." + FileUtil.getFileExtendName(zipPath));
try {
ImageOperation.thumbnailsImage(file, minFile, 300);
} catch (IOException e) {
@ -361,7 +361,7 @@ public class FileOperation {
public static long deleteFileFromDisk(String fileurl) {
String fileUrl = PathUtil.getStaticPath() + fileurl;
String extendName = FileUtil.getFileType(fileUrl);
String extendName = FileUtil.getFileExtendName(fileUrl);
String minFileUrl = fileUrl.replace("." + extendName, "_min." + extendName);
long filesize = getFileSize(fileUrl);

View File

@ -0,0 +1,7 @@
package com.qiwenshare.common.operation.delete;
import com.qiwenshare.common.domain.DeleteFile;
public abstract class Deleter {
public abstract void delete(DeleteFile deleteFile);
}

View File

@ -0,0 +1,32 @@
package com.qiwenshare.common.operation.delete.product;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.domain.DeleteFile;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class AliyunOSSDeleter extends Deleter {
@Resource
QiwenFileConfig qiwenFileConfig;
@Override
public void delete(DeleteFile deleteFile) {
// AliyunOSSDelete.deleteObject(qiwenFileConfig.getAliyun().getOss(), deleteFile.getFileUrl().substring(1));
String endpoint = qiwenFileConfig.getAliyun().getOss().getEndpoint();
String accessKeyId = qiwenFileConfig.getAliyun().getOss().getAccessKeyId();
String accessKeySecret = qiwenFileConfig.getAliyun().getOss().getAccessKeySecret();
String bucketName = qiwenFileConfig.getAliyun().getOss().getBucketName();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.deleteObject(bucketName, deleteFile.getFileUrl().substring(1));
// 关闭OSSClient
ossClient.shutdown();
}
}

View File

@ -0,0 +1,17 @@
package com.qiwenshare.common.operation.delete.product;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.domain.DeleteFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FastDFSDeleter extends Deleter {
@Autowired
private FastFileStorageClient fastFileStorageClient;
@Override
public void delete(DeleteFile deleteFile) {
fastFileStorageClient.deleteFile(deleteFile.getFileUrl());
}
}

View File

@ -0,0 +1,19 @@
package com.qiwenshare.common.operation.delete.product;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.domain.DeleteFile;
import com.qiwenshare.common.operation.FileOperation;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import org.springframework.stereotype.Component;
@Component
public class LocalStorageDeleter extends Deleter {
@Override
public void delete(DeleteFile deleteFile) {
FileOperation.deleteFile(PathUtil.getStaticPath() + deleteFile.getFileUrl());
if (FileUtil.isImageFile(FileUtil.getFileExtendName(deleteFile.getFileUrl()))) {
FileOperation.deleteFile(PathUtil.getStaticPath() + deleteFile.getFileUrl().replace(deleteFile.getTimeStampName(), deleteFile.getTimeStampName() + "_min"));
}
}
}

View File

@ -0,0 +1,9 @@
package com.qiwenshare.common.operation.download;
import com.qiwenshare.common.domain.DownloadFile;
import javax.servlet.http.HttpServletResponse;
public abstract class Downloader {
public abstract void download(HttpServletResponse httpServletResponse, DownloadFile uploadFile);
}

View File

@ -0,0 +1,62 @@
package com.qiwenshare.common.operation.download.product;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.common.domain.AliyunOSS;
import com.qiwenshare.common.domain.DownloadFile;
import com.qiwenshare.common.operation.download.Downloader;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@Component
public class AliyunOSSDownloader extends Downloader {
@Resource
QiwenFileConfig qiwenFileConfig;
@Override
public void download(HttpServletResponse httpServletResponse, DownloadFile downloadFile) {
BufferedInputStream bis = null;
byte[] buffer = new byte[1024];
OSS ossClient = createOSSClient(qiwenFileConfig.getAliyun().getOss());
OSSObject ossObject = ossClient.getObject(qiwenFileConfig.getAliyun().getOss().getBucketName(), downloadFile.getTimeStampName());
InputStream inputStream = ossObject.getObjectContent();
try {
bis = new BufferedInputStream(inputStream);
OutputStream os = httpServletResponse.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ossClient.shutdown();
}
public OSS createOSSClient(AliyunOSS aliyunOSS) {
String endpoint = aliyunOSS.getEndpoint();
String accessKeyId = aliyunOSS.getAccessKeyId();
String accessKeySecret = aliyunOSS.getAccessKeySecret();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
return ossClient;
}
}

View File

@ -0,0 +1,43 @@
package com.qiwenshare.common.operation.download.product;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.qiwenshare.common.domain.DownloadFile;
import com.qiwenshare.common.operation.download.Downloader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class FastDFSDownloader extends Downloader {
@Autowired
private FastFileStorageClient fastFileStorageClient;
@Override
public void download(HttpServletResponse httpServletResponse, DownloadFile downloadFile) {
String group = downloadFile.getFileUrl().substring(0, downloadFile.getFileUrl().indexOf("/"));
String path = downloadFile.getFileUrl().substring(downloadFile.getFileUrl().indexOf("/") + 1);
DownloadByteArray downloadByteArray = new DownloadByteArray();
byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
// // 这里只是为了整合fastdfs所以写死了文件格式需要在上传的时候保存文件名下载的时候使用对应的格式
// response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("sb.xlsx", "UTF-8"));
// response.setCharacterEncoding("UTF-8");
ServletOutputStream outputStream = null;
try {
outputStream = httpServletResponse.getOutputStream();
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,48 @@
package com.qiwenshare.common.operation.download.product;
import com.qiwenshare.common.domain.DownloadFile;
import com.qiwenshare.common.operation.FileOperation;
import com.qiwenshare.common.operation.download.Downloader;
import com.qiwenshare.common.util.PathUtil;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
@Component
public class LocalStorageDownloader extends Downloader {
@Override
public void download(HttpServletResponse httpServletResponse, DownloadFile downloadFile) {
BufferedInputStream bis = null;
byte[] buffer = new byte[1024];
//设置文件路径
File file = FileOperation.newFile(PathUtil.getStaticPath() + downloadFile.getFileUrl());
if (file.exists()) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = httpServletResponse.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}

View File

@ -1,12 +1,9 @@
package com.qiwenshare.common.upload;
package com.qiwenshare.common.operation.upload;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.util.PathUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
@ -26,14 +23,11 @@ public abstract class Uploader {
// 文件大小限制单位KB
public final int maxSize = 10000000;
protected StandardMultipartHttpServletRequest request = null;
public abstract List<UploadFile> upload(HttpServletRequest request);
public abstract List<UploadFile> upload(HttpServletRequest request, UploadFile uploadFile);
/**
* 根据字符串创建本地目录 并按照日期建立子目录返回
*
* @param path
* @return
*/
protected String getSaveFilePath() {
@ -75,7 +69,6 @@ public abstract class Uploader {
}
public synchronized boolean checkUploadStatus(UploadFile param, File confFile) throws IOException {
//File confFile = new File(savePath, timeStampName + ".conf");
RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw");
//设置文件长度
confAccessFile.setLength(param.getTotalChunks());

View File

@ -1,41 +1,36 @@
package com.qiwenshare.common.upload.product;
package com.qiwenshare.common.operation.upload.product;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.qiwenshare.common.domain.AliyunOSS;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.upload.Uploader;
import com.qiwenshare.common.exception.UploadGeneralException;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import lombok.Data;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component
public class AliyunOSSUploader extends Uploader {
private static final Logger logger = LoggerFactory.getLogger(AliyunOSSUploader.class);
@Resource
QiwenFileConfig qiwenFileConfig;
private UploadFile uploadFile;
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
// partETags是PartETag的集合PartETag由分片的ETag和分片号组成
public static Map<String, List<PartETag>> partETagsMap = new HashMap<String, List<PartETag>>();
@ -45,73 +40,49 @@ public class AliyunOSSUploader extends Uploader {
public static Map<String, String> timeStampNameMap = new HashMap<>();
public AliyunOSSUploader() {
}
public AliyunOSSUploader(UploadFile uploadFile) {
this.uploadFile = uploadFile;
}
@Override
public List<UploadFile> upload(HttpServletRequest httpServletRequest) {
public List<UploadFile> upload(HttpServletRequest httpServletRequest, UploadFile uploadFile) {
logger.info("开始上传upload");
List<UploadFile> saveUploadFileList = new ArrayList<>();
this.request = (StandardMultipartHttpServletRequest) httpServletRequest;
AliyunOSS aliyunOSS = (AliyunOSS) request.getAttribute("oss");
StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest) httpServletRequest;
endpoint = aliyunOSS.getEndpoint();
accessKeyId = aliyunOSS.getAccessKeyId();
accessKeySecret = aliyunOSS.getAccessKeySecret();
bucketName = aliyunOSS.getBucketName();
boolean isMultipart = ServletFileUpload.isMultipartContent(this.request);
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
UploadFile uploadFile = new UploadFile();
uploadFile.setSuccess(0);
uploadFile.setMessage("未包含文件上传域");
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
throw new UploadGeneralException("未包含文件上传域");
}
DiskFileItemFactory dff = new DiskFileItemFactory();//1创建工厂
String savePath = getSaveFilePath();
dff.setRepository(new File(savePath));
try {
ServletFileUpload sfu = new ServletFileUpload(dff);//2创建文件上传解析器
sfu.setSizeMax(this.maxSize * 1024L);
sfu.setHeaderEncoding("utf-8");//3解决文件名的中文乱码
Iterator<String> iter = this.request.getFileNames();
while (iter.hasNext()) {
ServletFileUpload sfu = new ServletFileUpload(dff);
sfu.setSizeMax(this.maxSize * 1024L);
sfu.setHeaderEncoding("utf-8");//3解决文件名的中文乱码
Iterator<String> iter = request.getFileNames();
while (iter.hasNext()) {
saveUploadFileList = doUpload(savePath, iter);
}
} catch (IOException e) {
UploadFile uploadFile = new UploadFile();
uploadFile.setSuccess(1);
uploadFile.setMessage("未知错误");
saveUploadFileList.add(uploadFile);
e.printStackTrace();
saveUploadFileList = doUpload(request, savePath, iter, uploadFile);
}
logger.info("结束上传");
return saveUploadFileList;
}
private List<UploadFile> doUpload(String savePath, Iterator<String> iter) throws IOException {
OSS ossClient = getClient();
private List<UploadFile> doUpload(StandardMultipartHttpServletRequest standardMultipartHttpServletRequest, String savePath, Iterator<String> iter, UploadFile uploadFile) {
OSS ossClient = getClient(uploadFile);
List<UploadFile> saveUploadFileList = new ArrayList<>();
try {
MultipartFile multipartfile = this.request.getFile(iter.next());
MultipartFile multipartfile = standardMultipartHttpServletRequest.getFile(iter.next());
String timeStampName = getTimeStampName();
String originalName = multipartfile.getOriginalFilename();
String fileName = getFileName(originalName);
String fileType = FileUtil.getFileType(originalName);
String fileType = FileUtil.getFileExtendName(originalName);
uploadFile.setFileName(fileName);
uploadFile.setFileType(fileType);
uploadFile.setTimeStampName(timeStampName);
@ -122,12 +93,12 @@ public class AliyunOSSUploader extends Uploader {
synchronized (AliyunOSSUploader.class) {
if (uploadPartRequestMap.get(uploadFile.getIdentifier()) == null) {
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, ossFilePath.substring(1));
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(qiwenFileConfig.getAliyun().getOss().getBucketName(), ossFilePath.substring(1));
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
String uploadId = upresult.getUploadId();
UploadFileInfo uploadPartRequest = new UploadFileInfo();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setBucketName(qiwenFileConfig.getAliyun().getOss().getBucketName());
uploadPartRequest.setKey(ossFilePath.substring(1));
uploadPartRequest.setUploadId(uploadId);
uploadPartRequestMap.put(uploadFile.getIdentifier(), uploadPartRequest);
@ -166,7 +137,7 @@ public class AliyunOSSUploader extends Uploader {
boolean isComplete = checkUploadStatus(uploadFile, confFile);
if (isComplete) {
logger.info("分片上传完成");
completeMultipartUpload();
completeMultipartUpload(uploadFile);
uploadFile.setUrl(ossFilePath);
uploadFile.setSuccess(1);
@ -178,9 +149,11 @@ public class AliyunOSSUploader extends Uploader {
} catch (Exception e) {
logger.error("上传出错:" + e);
throw new UploadGeneralException(e);
}
uploadFile.setIsOSS(1);
uploadFile.setStorageType(1);
uploadFile.setFileSize(uploadFile.getTotalSize());
saveUploadFileList.add(uploadFile);
@ -190,37 +163,37 @@ public class AliyunOSSUploader extends Uploader {
/**
* 将文件分块进行升序排序并执行文件上传
*/
protected void completeMultipartUpload() {
protected void completeMultipartUpload(UploadFile uploadFile) {
List<PartETag> partETags = partETagsMap.get(uploadFile.getIdentifier());
Collections.sort(partETags, Comparator.comparingInt(PartETag::getPartNumber));
UploadFileInfo uploadFileInfo = uploadPartRequestMap.get(uploadFile.getIdentifier());
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName,
new CompleteMultipartUploadRequest(qiwenFileConfig.getAliyun().getOss().getBucketName(),
uploadFileInfo.getKey(),
uploadFileInfo.getUploadId(),
partETags);
logger.info("----:" + JSON.toJSONString(partETags));
// 完成上传
CompleteMultipartUploadResult completeMultipartUploadResult = getClient().completeMultipartUpload(completeMultipartUploadRequest);
CompleteMultipartUploadResult completeMultipartUploadResult = getClient(uploadFile).completeMultipartUpload(completeMultipartUploadRequest);
logger.info("----:" + JSON.toJSONString(completeMultipartUploadRequest));
getClient().shutdown();
getClient(uploadFile).shutdown();
partETagsMap.remove(uploadFile.getIdentifier());
uploadPartRequestMap.remove(uploadFile.getIdentifier());
ossMap.remove(uploadFile.getIdentifier());
//
}
private void listFile() {
private void listFile(UploadFile uploadFile) {
// 列举已上传的分片其中uploadId来自于InitiateMultipartUpload返回的结果
ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());
ListPartsRequest listPartsRequest = new ListPartsRequest(qiwenFileConfig.getAliyun().getOss().getBucketName(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());
// 设置uploadId
//listPartsRequest.setUploadId(uploadId);
// 设置分页时每一页中分片数量为100个默认列举1000个分片
listPartsRequest.setMaxParts(100);
// 指定List的起始位置只有分片号大于此参数值的分片会被列举
// listPartsRequest.setPartNumberMarker(1);
PartListing partListing = getClient().listParts(listPartsRequest);
PartListing partListing = getClient(uploadFile).listParts(listPartsRequest);
for (PartSummary part : partListing.getParts()) {
logger.info("分片号:"+part.getPartNumber() + ", 分片数据大小: "+
@ -241,13 +214,14 @@ public class AliyunOSSUploader extends Uploader {
/**
* 取消上传
*/
private void cancelUpload() {
private void cancelUpload(UploadFile uploadFile) {
AbortMultipartUploadRequest abortMultipartUploadRequest =
new AbortMultipartUploadRequest(bucketName, uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());
getClient().abortMultipartUpload(abortMultipartUploadRequest);
new AbortMultipartUploadRequest(qiwenFileConfig.getAliyun().getOss().getBucketName(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());
getClient(uploadFile).abortMultipartUpload(abortMultipartUploadRequest);
}
protected synchronized String getTimeStampName(){
protected synchronized String getTimeStampName(UploadFile uploadFile){
String timeStampName;
if (StringUtils.isEmpty(timeStampNameMap.get(uploadFile.getIdentifier()))) {
@ -259,10 +233,10 @@ public class AliyunOSSUploader extends Uploader {
return timeStampName;
}
private synchronized OSS getClient() {
private synchronized OSS getClient(UploadFile uploadFile) {
OSS ossClient = null;
if (ossMap.get(uploadFile.getIdentifier()) == null) {
ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient = new OSSClientBuilder().build(qiwenFileConfig.getAliyun().getOss().getEndpoint(), qiwenFileConfig.getAliyun().getOss().getAccessKeyId(), qiwenFileConfig.getAliyun().getOss().getAccessKeySecret());
ossMap.put(uploadFile.getIdentifier(), ossClient);
} else {
ossClient = ossMap.get(uploadFile.getIdentifier());

View File

@ -0,0 +1,197 @@
package com.qiwenshare.common.operation.upload.product;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.AppendFileStorageClient;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.exception.UploadGeneralException;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;
@Component
@Slf4j
public class FastDFSUploader extends Uploader {
public static Object lock = new Object();
@Resource
AppendFileStorageClient defaultAppendFileStorageClient;
private static Map<String, Integer> CURRENT_UPLOAD_CHUNK_NUMBER = new HashMap<>();
private static Map<String, Long> UPLOADED_SIZE = new HashMap<>();
private static Map<String, String> STORE_PATH = new HashMap<>();
private static Map<String, Object> LOCK_MAP = new HashMap<>();
@Override
public List<UploadFile> upload(HttpServletRequest request, UploadFile uploadFile) {
log.info("开始上传upload");
List<UploadFile> saveUploadFileList = new ArrayList<>();
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = (StandardMultipartHttpServletRequest) request;
boolean isMultipart = ServletFileUpload.isMultipartContent(standardMultipartHttpServletRequest);
if (!isMultipart) {
throw new UploadGeneralException("未包含文件上传域");
}
DiskFileItemFactory dff = new DiskFileItemFactory();//1创建工厂
String savePath = getSaveFilePath();
dff.setRepository(new File(savePath));
try {
ServletFileUpload sfu = new ServletFileUpload(dff);//2创建文件上传解析器
sfu.setSizeMax(this.maxSize * 1024L);
sfu.setHeaderEncoding("utf-8");//3解决文件名的中文乱码
Iterator<String> iter = standardMultipartHttpServletRequest.getFileNames();
while (iter.hasNext()) {
saveUploadFileList = doUpload(standardMultipartHttpServletRequest, savePath, iter, uploadFile);
}
} catch (Exception e) {
throw new UploadGeneralException(e);
}
log.info("结束上传");
return saveUploadFileList;
}
private List<UploadFile> doUpload(StandardMultipartHttpServletRequest standardMultipartHttpServletRequest, String savePath, Iterator<String> iter, UploadFile uploadFile) {
List<UploadFile> saveUploadFileList = new ArrayList<>();
try {
MultipartFile multipartfile = standardMultipartHttpServletRequest.getFile(iter.next());
synchronized (lock) {
if (LOCK_MAP.get(uploadFile.getIdentifier()) == null) {
LOCK_MAP.put(uploadFile.getIdentifier(), new Object());
}
}
uploadFileChunk(multipartfile, uploadFile);
String timeStampName = getTimeStampName();
String originalName = multipartfile.getOriginalFilename();
String fileName = getFileName(originalName);
String fileType = FileUtil.getFileExtendName(originalName);
uploadFile.setFileName(fileName);
uploadFile.setFileType(fileType);
uploadFile.setTimeStampName(timeStampName);
String confFilePath = savePath + FILE_SEPARATOR + uploadFile.getIdentifier() + "." + "conf";
File confFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + confFilePath);
boolean isComplete = checkUploadStatus(uploadFile, confFile);
if (isComplete) {
log.info("分片上传完成");
LOCK_MAP.remove(uploadFile.getIdentifier());
uploadFile.setUrl(STORE_PATH.get(uploadFile.getIdentifier()));
uploadFile.setSuccess(1);
uploadFile.setMessage("上传成功");
} else {
uploadFile.setSuccess(0);
uploadFile.setMessage("未完成");
}
} catch (Exception e) {
throw new UploadGeneralException(e);
}
uploadFile.setIsOSS(0);
uploadFile.setStorageType(2);
uploadFile.setFileSize(uploadFile.getTotalSize());
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
}
public void uploadFileChunk(MultipartFile multipartFile, UploadFile uploadFile) {
synchronized (LOCK_MAP.get(uploadFile.getIdentifier())) {
// 存储在fastdfs不带组的路径
log.info("当前文件的Md5:{}", uploadFile.getIdentifier());
log.info("当前块的大小:{}", uploadFile.getCurrentChunkSize());
if (CURRENT_UPLOAD_CHUNK_NUMBER.get(uploadFile.getIdentifier()) == null) {
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), 1);
}
while (uploadFile.getChunkNumber() != CURRENT_UPLOAD_CHUNK_NUMBER.get(uploadFile.getIdentifier())) {
try {
LOCK_MAP.get(uploadFile.getIdentifier()).wait();
} catch (InterruptedException e) {
log.error("--------InterruptedException-------");
e.printStackTrace();
}
}
log.info("***********开始上传第{}块**********", uploadFile.getChunkNumber());
StorePath storePath = null;
try {
if (uploadFile.getChunkNumber() <= 1) {
log.info("上传第一块");
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), uploadFile.getChunkNumber() + 1);
try {
storePath = defaultAppendFileStorageClient.uploadAppenderFile("group1", multipartFile.getInputStream(),
multipartFile.getSize(), FileUtil.getFileExtendName(multipartFile.getOriginalFilename()));
// 记录第一个分片上传的大小
UPLOADED_SIZE.put(uploadFile.getIdentifier(), uploadFile.getCurrentChunkSize());
log.info("第一块上传完成");
if (storePath == null) {
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), uploadFile.getChunkNumber());
log.info("获取远程文件路径出错");
throw new UploadGeneralException("获取远程文件路径出错");
}
} catch (Exception e) {
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), uploadFile.getChunkNumber());
log.error("初次上传远程文件出错", e);
throw new UploadGeneralException("初次上传远程文件出错", e);
}
STORE_PATH.put(uploadFile.getIdentifier(), storePath.getPath());
log.info("上传文件 result = {}", storePath.getPath());
} else {
log.info("上传第{}块:" + uploadFile.getChunkNumber());
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), uploadFile.getChunkNumber() + 1);
String path = STORE_PATH.get(uploadFile.getIdentifier());
if (path == null) {
log.error("无法获取已上传服务器文件地址");
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), uploadFile.getChunkNumber());
throw new UploadGeneralException("无法获取已上传服务器文件地址");
}
try {
Long alreadySize = UPLOADED_SIZE.get(uploadFile.getIdentifier());
// 追加方式实际实用如果中途出错多次,可能会出现重复追加情况,这里改成修改模式,即时多次传来重复文件块,依然可以保证文件拼接正确
defaultAppendFileStorageClient.modifyFile("group1", path, multipartFile.getInputStream(),
multipartFile.getSize(), alreadySize);
// 记录分片上传的大小
UPLOADED_SIZE.put(uploadFile.getIdentifier(), alreadySize + multipartFile.getSize());
log.info("第{}块更新完成", uploadFile.getChunkNumber());
} catch (Exception e) {
CURRENT_UPLOAD_CHUNK_NUMBER.put(uploadFile.getIdentifier(), uploadFile.getChunkNumber());
log.error("更新远程文件出错", e);
throw new UploadGeneralException("更新远程文件出错", e);
}
}
} catch (Exception e) {
log.error("上传文件错误", e);
throw new UploadGeneralException("上传文件错误", e);
}
log.info("***********第{}块上传成功**********", uploadFile.getChunkNumber());
LOCK_MAP.get(uploadFile.getIdentifier()).notifyAll();
}
}
}

View File

@ -1,18 +1,19 @@
package com.qiwenshare.common.upload.product;
package com.qiwenshare.common.operation.upload.product;
import com.qiwenshare.common.cbb.NotSameFileExpection;
import com.qiwenshare.common.exception.NotSameFileExpection;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.exception.UploadGeneralException;
import com.qiwenshare.common.operation.ImageOperation;
import com.qiwenshare.common.upload.Uploader;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
@ -24,30 +25,26 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@Component
public class LocalStorageUploader extends Uploader {
private static final Logger logger = LoggerFactory.getLogger(LocalStorageUploader.class);
// private UploadFile uploadFile;
public class ChunkUploader extends Uploader {
private static final Logger logger = LoggerFactory.getLogger(ChunkUploader.class);
private UploadFile uploadFile;
public ChunkUploader() {
public LocalStorageUploader() {
}
public ChunkUploader(UploadFile uploadFile) {
this.uploadFile = uploadFile;
}
//
// public ChunkUploader(UploadFile uploadFile) {
// this.uploadFile = uploadFile;
// }
@Override
public List<UploadFile> upload(HttpServletRequest httpServletRequest) {
public List<UploadFile> upload(HttpServletRequest httpServletRequest,UploadFile uploadFile) {
List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
this.request = (StandardMultipartHttpServletRequest) httpServletRequest;
boolean isMultipart = ServletFileUpload.isMultipartContent(this.request);
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = (StandardMultipartHttpServletRequest) httpServletRequest;
boolean isMultipart = ServletFileUpload.isMultipartContent(standardMultipartHttpServletRequest);
if (!isMultipart) {
UploadFile uploadFile = new UploadFile();
uploadFile.setSuccess(0);
uploadFile.setMessage("未包含文件上传域");
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
throw new UploadGeneralException("未包含文件上传域");
}
DiskFileItemFactory dff = new DiskFileItemFactory();//1创建工厂
String savePath = getSaveFilePath();
@ -57,43 +54,28 @@ public class ChunkUploader extends Uploader {
ServletFileUpload sfu = new ServletFileUpload(dff);//2创建文件上传解析器
sfu.setSizeMax(this.maxSize * 1024L);
sfu.setHeaderEncoding("utf-8");//3解决文件名的中文乱码
Iterator<String> iter = this.request.getFileNames();
Iterator<String> iter = standardMultipartHttpServletRequest.getFileNames();
while (iter.hasNext()) {
saveUploadFileList = doUpload(savePath, iter);
saveUploadFileList = doUpload(standardMultipartHttpServletRequest, savePath, iter, uploadFile);
}
} catch (IOException e) {
UploadFile uploadFile = new UploadFile();
uploadFile.setSuccess(1);
uploadFile.setMessage("未知错误");
saveUploadFileList.add(uploadFile);
e.printStackTrace();
throw new UploadGeneralException("未包含文件上传域");
} catch (NotSameFileExpection notSameFileExpection) {
notSameFileExpection.printStackTrace();
}
return saveUploadFileList;
}
private List<UploadFile> doUpload(String savePath, Iterator<String> iter) throws IOException, NotSameFileExpection {
private List<UploadFile> doUpload(StandardMultipartHttpServletRequest standardMultipartHttpServletRequest, String savePath, Iterator<String> iter, UploadFile uploadFile) throws IOException, NotSameFileExpection {
List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
//UploadFile uploadFile = new UploadFile();
MultipartFile multipartfile = this.request.getFile(iter.next());
MultipartFile multipartfile = standardMultipartHttpServletRequest.getFile(iter.next());
//InputStream inputStream = multipartfile.getInputStream();
String timeStampName = uploadFile.getIdentifier();
// .getTimeStampName();
// if (StringUtils.isEmpty(uploadFile.getTimeStampName())) {
// timeStampName = getTimeStampName();
// }
String originalName = multipartfile.getOriginalFilename();
String fileName = getFileName(originalName);
String fileType = FileUtil.getFileType(originalName);
String fileType = FileUtil.getFileExtendName(originalName);
uploadFile.setFileName(fileName);
uploadFile.setFileType(fileType);
uploadFile.setTimeStampName(timeStampName);
@ -107,6 +89,7 @@ public class ChunkUploader extends Uploader {
File minFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + minFilePath);
File confFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + confFilePath);
uploadFile.setIsOSS(0);
uploadFile.setStorageType(0);
uploadFile.setUrl(saveFilePath);
if (StringUtils.isEmpty(uploadFile.getTaskId())) {// == null || "".equals(uploadFile.getTaskId())) {

View File

@ -0,0 +1,136 @@
//package com.qiwenshare.common.upload.product;
//
//import com.qiwenshare.common.domain.UploadFile;
//import com.qiwenshare.common.operation.ImageOperation;
//import com.qiwenshare.common.upload.Uploader;
//import com.qiwenshare.common.util.FileUtil;
//import com.qiwenshare.common.util.PathUtil;
//import org.apache.commons.fileupload.disk.DiskFileItemFactory;
//import org.apache.commons.fileupload.servlet.ServletFileUpload;
//import org.apache.commons.fileupload.util.Streams;
//import org.apache.commons.lang3.StringUtils;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.web.multipart.MultipartFile;
//import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
//
//import javax.servlet.http.HttpServletRequest;
//import java.io.*;
//import java.util.ArrayList;
//import java.util.Iterator;
//import java.util.List;
//
//public class NormalUploader extends Uploader {
// private static final Logger logger = LoggerFactory.getLogger(NormalUploader.class);
//
// @Override
// public List<UploadFile> upload(HttpServletRequest httpServletRequest) {
// List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
// this.request = (StandardMultipartHttpServletRequest) httpServletRequest;
// boolean isMultipart = ServletFileUpload.isMultipartContent(this.request);
// if (!isMultipart) {
// UploadFile uploadFile = new UploadFile();
// uploadFile.setSuccess(0);
// uploadFile.setMessage("未包含文件上传域");
// saveUploadFileList.add(uploadFile);
// return saveUploadFileList;
// }
// DiskFileItemFactory dff = new DiskFileItemFactory();//1创建工厂
// String savePath = getSaveFilePath();
// dff.setRepository(new File(savePath));
//
// try {
// ServletFileUpload sfu = new ServletFileUpload(dff);//2创建文件上传解析器
// sfu.setSizeMax(this.maxSize * 1024L);
// sfu.setHeaderEncoding("utf-8");//3解决文件名的中文乱码
// Iterator<String> iter = this.request.getFileNames();
// while (iter.hasNext()) {
// saveUploadFileList = doUpload(savePath, iter);
// }
// } catch (IOException e) {
// UploadFile uploadFile = new UploadFile();
// uploadFile.setSuccess(1);
// uploadFile.setMessage("未知错误");
// saveUploadFileList.add(uploadFile);
// e.printStackTrace();
// }
//
// return saveUploadFileList;
// }
//
// private List<UploadFile> doUpload(String savePath, Iterator<String> iter) throws IOException {
// List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
// UploadFile uploadFile = new UploadFile();
// MultipartFile multipartfile = this.request.getFile(iter.next());
//
// InputStream inputStream = multipartfile.getInputStream();
// String timeStampName = getTimeStampName();
//
//
// String originalName = multipartfile.getOriginalFilename();
//
// String fileName = getFileName(originalName);
//
// String fileType = FileUtil.getFileExtendName(originalName);
// uploadFile.setFileName(fileName);
// uploadFile.setFileType(fileType);
// uploadFile.setTimeStampName(timeStampName);
//
// String saveFilePath = savePath + FILE_SEPARATOR + timeStampName;
// String minFilePath = savePath + FILE_SEPARATOR + timeStampName;
// if (StringUtils.isNotEmpty(fileType)) {
// saveFilePath += "." + fileType;
// minFilePath += "_min" + "." + fileType;
// }
//
// File file = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + saveFilePath);
// File minFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + minFilePath);
//
// uploadFile.setIsOSS(0);
// uploadFile.setStorageType(0);
// uploadFile.setUrl(saveFilePath);
// BufferedInputStream in = null;
// FileOutputStream out = null;
// BufferedOutputStream output = null;
//
// try {
// in = new BufferedInputStream(inputStream);
// out = new FileOutputStream(file);
// output = new BufferedOutputStream(out);
// Streams.copy(in, output, true);
// if (FileUtil.isImageFile(uploadFile.getFileType())){
// ImageOperation.thumbnailsImage(file, minFile, 300);
// }
//
// } catch (FileNotFoundException e) {
// logger.error("文件没有发现" + e);
// } catch (IOException e) {
// logger.error("文件读取失败" + e);
// } finally {
//
// closeStream(in, out, output);
// }
//
//
//
// uploadFile.setSuccess(1);
// uploadFile.setMessage("上传成功");
// uploadFile.setFileSize(request.getContentLengthLong());
// saveUploadFileList.add(uploadFile);
// return saveUploadFileList;
// }
//
//
// private void closeStream(BufferedInputStream in, FileOutputStream out,
// BufferedOutputStream output) throws IOException {
// if (in != null) {
// in.close();
// }
// if (out != null) {
// out.close();
// }
// if (output != null) {
// output.close();
// }
// }
//}

View File

@ -1,55 +0,0 @@
/**
* 示例说明
*
* HelloOSS是OSS Java SDK的示例程序您可以修改endpointaccessKeyIdaccessKeySecretbucketName后直接运行
* 运行方法请参考README
*
* 本示例中的并不包括OSS Java SDK的所有功能详细功能及使用方法请参看SDK手册 > Java-SDK
* 链接地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/preface.html?spm=5176.docoss/sdk/java-sdk/
*
* 调用OSS Java SDK的方法时抛出异常表示有错误发生没有抛出异常表示成功执行
* 当错误发生时OSS Java SDK的方法会抛出异常异常中包括错误码错误信息详细请参看SDK手册 > Java-SDK > 异常处理
* 链接地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/exception.html?spm=5176.docoss/api-reference/error-response
*
* OSS控制台可以直观的看到您调用OSS Java SDK的结果OSS控制台地址是https://oss.console.aliyun.com/index#/
* OSS控制台使用方法请参看文档中心的控制台用户指南 指南的来链接地址是https://help.aliyun.com/document_detail/oss/getting-started/get-started.html?spm=5176.docoss/user_guide
*
* OSS的文档中心地址是https://help.aliyun.com/document_detail/oss/user_guide/overview.html
* OSS Java SDK的文档地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/install.html?spm=5176.docoss/sdk/java-sdk
*
*/
package com.qiwenshare.common.oss;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.qiwenshare.common.domain.AliyunOSS;
import com.qiwenshare.common.util.FileUtil;
import java.io.InputStream;
public class AliyunOSSDelete {
/**
* 流式上传
*/
public static void deleteObject(AliyunOSS aliyunOSS, String objectName) {
String endpoint = aliyunOSS.getEndpoint();
String accessKeyId = aliyunOSS.getAccessKeyId();
String accessKeySecret = aliyunOSS.getAccessKeySecret();
String bucketName = aliyunOSS.getBucketName();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.deleteObject(bucketName, objectName);
// 关闭OSSClient
ossClient.shutdown();
}
}

View File

@ -1,38 +0,0 @@
package com.qiwenshare.common.oss;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.qiwenshare.common.domain.AliyunOSS;
import java.io.InputStream;
public class AliyunOSSDownload {
private String endpoint = "";
private String accessKeyId = "";
private String accessKeySecret = "";
private String bucketName = "";
public OSS createOSSClient(AliyunOSS aliyunOSS) {
String endpoint = aliyunOSS.getEndpoint();
String accessKeyId = aliyunOSS.getAccessKeyId();
String accessKeySecret = aliyunOSS.getAccessKeySecret();
this.bucketName = aliyunOSS.getBucketName();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
return ossClient;
}
/**
* 流式下载
*/
public InputStream streamDownload(String objectName) {
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// ossObject包含文件所在的存储空间名称文件名称文件元信息以及一个输入流
OSSObject ossObject = ossClient.getObject(bucketName, objectName);
return ossObject.getObjectContent();
}
}

View File

@ -1,59 +0,0 @@
/**
* 示例说明
*
* HelloOSS是OSS Java SDK的示例程序您可以修改endpointaccessKeyIdaccessKeySecretbucketName后直接运行
* 运行方法请参考README
*
* 本示例中的并不包括OSS Java SDK的所有功能详细功能及使用方法请参看SDK手册 > Java-SDK
* 链接地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/preface.html?spm=5176.docoss/sdk/java-sdk/
*
* 调用OSS Java SDK的方法时抛出异常表示有错误发生没有抛出异常表示成功执行
* 当错误发生时OSS Java SDK的方法会抛出异常异常中包括错误码错误信息详细请参看SDK手册 > Java-SDK > 异常处理
* 链接地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/exception.html?spm=5176.docoss/api-reference/error-response
*
* OSS控制台可以直观的看到您调用OSS Java SDK的结果OSS控制台地址是https://oss.console.aliyun.com/index#/
* OSS控制台使用方法请参看文档中心的控制台用户指南 指南的来链接地址是https://help.aliyun.com/document_detail/oss/getting-started/get-started.html?spm=5176.docoss/user_guide
*
* OSS的文档中心地址是https://help.aliyun.com/document_detail/oss/user_guide/overview.html
* OSS Java SDK的文档地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/install.html?spm=5176.docoss/sdk/java-sdk
*
*/
package com.qiwenshare.common.oss;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.qiwenshare.common.domain.AliyunOSS;
import java.io.InputStream;
public class AliyunOSSRename {
/**
* 流式上传
*/
public static void rename(AliyunOSS aliyunOSS, String sourceObjectName, String destinationObjectName) {
String endpoint = aliyunOSS.getEndpoint();
String accessKeyId = aliyunOSS.getAccessKeyId();
String accessKeySecret = aliyunOSS.getAccessKeySecret();
String bucketName = aliyunOSS.getBucketName();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
CopyObjectResult result = ossClient.copyObject(bucketName, sourceObjectName, bucketName, destinationObjectName);
ossClient.deleteObject(bucketName, sourceObjectName);
ObjectMetadata metadata = new ObjectMetadata();
// if ("pdf".equals(FileUtil.getFileType(objectName))) {
// metadata.setContentDisposition("attachment");
// }
// ossClient.putObject(bucketName, objectName, inputStream, metadata);
// 关闭OSSClient
ossClient.shutdown();
}
}

View File

@ -1,10 +1,8 @@
package com.qiwenshare.common.cbb;
package com.qiwenshare.common.result;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Map;
/**
* 统一结果返回
* @param <T>

View File

@ -1,4 +1,4 @@
package com.qiwenshare.common.cbb;
package com.qiwenshare.common.result;
import lombok.Getter;
@ -12,6 +12,7 @@ public enum ResultCodeEnum {
PARAM_ERROR(false,20002,"参数错误"),
NULL_POINT(false, 20003, "空指针异常"),
INDEX_OUT_OF_BOUNDS(false, 20004, "下标越界异常"),
REQUEST_TIMEOUT(false, 20005, "请求超时"),
;
// 响应是否成功

View File

@ -1,18 +0,0 @@
package com.qiwenshare.common.upload.factory;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.upload.product.AliyunOSSUploader;
import com.qiwenshare.common.upload.Uploader;
public class AliyunOSSUploaderFactory implements UploaderFactory {
@Override
public Uploader getUploader() {
return new AliyunOSSUploader();
}
@Override
public Uploader getUploader(UploadFile uploadFile) {
return new AliyunOSSUploader(uploadFile);
}
}

View File

@ -1,20 +0,0 @@
package com.qiwenshare.common.upload.factory;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.upload.product.ChunkUploader;
import com.qiwenshare.common.upload.Uploader;
public class ChunkUploaderFactory implements UploaderFactory {
@Override
public Uploader getUploader() {
return new ChunkUploader();
}
@Override
public Uploader getUploader(UploadFile uploadFile) {
return new ChunkUploader(uploadFile);
}
}

View File

@ -1,18 +0,0 @@
package com.qiwenshare.common.upload.factory;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.upload.product.NormalUploader;
import com.qiwenshare.common.upload.Uploader;
public class NormalUploaderFactory implements UploaderFactory {
@Override
public Uploader getUploader() {
return new NormalUploader();
}
@Override
public Uploader getUploader(UploadFile uploadFile) {
return new NormalUploader();
}
}

View File

@ -1,9 +0,0 @@
package com.qiwenshare.common.upload.factory;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.upload.Uploader;
public interface UploaderFactory {
Uploader getUploader();
Uploader getUploader(UploadFile uploadFile);
}

View File

@ -1,135 +0,0 @@
package com.qiwenshare.common.upload.product;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.operation.ImageOperation;
import com.qiwenshare.common.upload.Uploader;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class NormalUploader extends Uploader {
private static final Logger logger = LoggerFactory.getLogger(NormalUploader.class);
@Override
public List<UploadFile> upload(HttpServletRequest httpServletRequest) {
List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
this.request = (StandardMultipartHttpServletRequest) httpServletRequest;
boolean isMultipart = ServletFileUpload.isMultipartContent(this.request);
if (!isMultipart) {
UploadFile uploadFile = new UploadFile();
uploadFile.setSuccess(0);
uploadFile.setMessage("未包含文件上传域");
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
}
DiskFileItemFactory dff = new DiskFileItemFactory();//1创建工厂
String savePath = getSaveFilePath();
dff.setRepository(new File(savePath));
try {
ServletFileUpload sfu = new ServletFileUpload(dff);//2创建文件上传解析器
sfu.setSizeMax(this.maxSize * 1024L);
sfu.setHeaderEncoding("utf-8");//3解决文件名的中文乱码
Iterator<String> iter = this.request.getFileNames();
while (iter.hasNext()) {
saveUploadFileList = doUpload(savePath, iter);
}
} catch (IOException e) {
UploadFile uploadFile = new UploadFile();
uploadFile.setSuccess(1);
uploadFile.setMessage("未知错误");
saveUploadFileList.add(uploadFile);
e.printStackTrace();
}
return saveUploadFileList;
}
private List<UploadFile> doUpload(String savePath, Iterator<String> iter) throws IOException {
List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
UploadFile uploadFile = new UploadFile();
MultipartFile multipartfile = this.request.getFile(iter.next());
InputStream inputStream = multipartfile.getInputStream();
String timeStampName = getTimeStampName();
String originalName = multipartfile.getOriginalFilename();
String fileName = getFileName(originalName);
String fileType = FileUtil.getFileType(originalName);
uploadFile.setFileName(fileName);
uploadFile.setFileType(fileType);
uploadFile.setTimeStampName(timeStampName);
String saveFilePath = savePath + FILE_SEPARATOR + timeStampName;
String minFilePath = savePath + FILE_SEPARATOR + timeStampName;
if (StringUtils.isNotEmpty(fileType)) {
saveFilePath += "." + fileType;
minFilePath += "_min" + "." + fileType;
}
File file = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + saveFilePath);
File minFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + minFilePath);
uploadFile.setIsOSS(0);
uploadFile.setUrl(saveFilePath);
BufferedInputStream in = null;
FileOutputStream out = null;
BufferedOutputStream output = null;
try {
in = new BufferedInputStream(inputStream);
out = new FileOutputStream(file);
output = new BufferedOutputStream(out);
Streams.copy(in, output, true);
if (FileUtil.isImageFile(uploadFile.getFileType())){
ImageOperation.thumbnailsImage(file, minFile, 300);
}
} catch (FileNotFoundException e) {
logger.error("文件没有发现" + e);
} catch (IOException e) {
logger.error("文件读取失败" + e);
} finally {
closeStream(in, out, output);
}
uploadFile.setSuccess(1);
uploadFile.setMessage("上传成功");
uploadFile.setFileSize(request.getContentLengthLong());
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
}
private void closeStream(BufferedInputStream in, FileOutputStream out,
BufferedOutputStream output) throws IOException {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (output != null) {
output.close();
}
}
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.common.cbb;
package com.qiwenshare.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.common.cbb;
package com.qiwenshare.common.util;
import java.text.DateFormat;
import java.text.ParseException;
@ -7,6 +7,7 @@ import java.util.Calendar;
import java.util.Date;
public class DateUtil {
/**
* 获取系统当前时间
*

View File

@ -1,6 +1,5 @@
package com.qiwenshare.common.util;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -74,7 +73,7 @@ public class FileUtil {
* @param fileName 文件名
* @return 文件扩展名
*/
public static String getFileType(String fileName) {
public static String getFileExtendName(String fileName) {
if (fileName.lastIndexOf(".") == -1) {
return "";
//这里暂时用jpg后续应该去获取真实的文件类型
@ -89,7 +88,7 @@ public class FileUtil {
* @return 文件名不带扩展名
*/
public static String getFileNameNotExtend(String fileName) {
String fileType = getFileType(fileName);
String fileType = getFileExtendName(fileName);
return fileName.replace("." + fileType, "");
}

View File

@ -1,4 +0,0 @@
package com.qiwenshare.common.util;
public class OfficeUtil {
}

View File

@ -1,24 +0,0 @@
package com.qiwenshare.common.util;
import java.util.Random;
public class RandomUtil {
public static String getStringRandom(int length) {
String val = "";
Random random = new Random();
//参数length表示生成几位随机数
for(int i = 0; i < length; i++) {
String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
//输出字母还是数字
if("char".equalsIgnoreCase(charOrNum)){
//输出是大写字母还是小写字母
int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char)(random.nextInt(26) + temp);
}else if("num".equalsIgnoreCase(charOrNum)) {
val += String.valueOf(random.nextInt(10));
}
}
return val;
}
}

View File

@ -0,0 +1,218 @@
package com.qiwenshare.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* redis实现分布式锁
*
*/
public class RedisLockUtils {
private static final Logger log = LoggerFactory.getLogger(RedisLockUtils.class);
/**
* 默认轮休获取锁间隔时间 单位毫秒
*/
private static final int DEFAULT_ACQUIRE_RESOLUTION_MILLIS = 100;
private static final String UNLOCK_LUA;
static {
StringBuilder lua = new StringBuilder();
lua.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
lua.append("then ");
lua.append(" return redis.call(\"del\",KEYS[1]) ");
lua.append("else ");
lua.append(" return 0 ");
lua.append("end ");
UNLOCK_LUA = lua.toString();
}
private RedisTemplate redisTemplate;
private final ThreadLocal<Map<String, LockVO>> lockMap = new ThreadLocal<>();
public RedisLockUtils(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 获取锁没有获取到则一直等待
*
* @param key redis key
* @param expire 锁过期时间, 单位
*/
public void lock(final String key, long expire) {
try {
acquireLock(key, expire, -1);
} catch (Exception e) {
throw new RuntimeException("acquire lock exception", e);
}
}
/**
* 获取锁指定时间内没有获取到返回false否则 返回true
*
* @param key redis key
* @param expire 锁过期时间, 单位
* @param waitTime 获取锁超时时间, -1代表永不超时, 单位
*/
public boolean tryLock(final String key, long expire, long waitTime) {
try {
return acquireLock(key, expire, waitTime);
} catch (Exception e) {
throw new RuntimeException("acquire lock exception", e);
}
}
/**
* 释放锁
*
* @param key redis key
*/
public void unlock(String key) {
try {
release(key);
} catch (Exception e) {
throw new RuntimeException("release lock exception", e);
}
}
/**
* @param key redis key
* @param expire 锁过期时间, 单位
* @param waitTime 获取锁超时时间, -1代表永不超时, 单位
* @return if true success else fail
* @throws InterruptedException 阻塞方法收到中断请求
*/
private boolean acquireLock(String key, long expire, long waitTime) throws InterruptedException {
//如果之前获取到了并且没有超时则返回获取成功
boolean acquired = acquired(key);
if (acquired) {
return true;
}
long acquireTime = waitTime == -1 ? -1 : waitTime * 1000 + System.currentTimeMillis();
//同一个进程对于同一个key锁只允许先到的去尝试获取
// key.intern() 如果常量池中存在当前字符串, 就会直接返回当前字符串.
// 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回
synchronized (key.intern()) {
String lockId = UUID.randomUUID().toString();
do {
long before = System.currentTimeMillis();
boolean hasLock = tryLock(key, expire, lockId);
//获取锁成功
if (hasLock) {
long after = System.currentTimeMillis();
Map<String, LockVO> map = lockMap.get();
if (map == null) {
map = new HashMap<>(2);
lockMap.set(map);
}
map.put(key, new LockVO(1, lockId, expire * 1000 + before, expire * 1000 + after));
log.debug("acquire lock {} {} ", key, 1);
return true;
}
Thread.sleep(DEFAULT_ACQUIRE_RESOLUTION_MILLIS);
} while (acquireTime == -1 || acquireTime > System.currentTimeMillis());
}
log.debug("acquire lock {} failbecause timeout ", key);
return false;
}
private boolean acquired(String key) {
Map<String, LockVO> map = lockMap.get();
if (map == null || map.size() == 0 || !map.containsKey(key)) {
return false;
}
LockVO vo = map.get(key);
if (vo.beforeExpireTime < System.currentTimeMillis()) {
log.debug("lock {} maybe release, because timeout ", key);
return false;
}
int after = ++vo.count;
log.debug("acquire lock {} {} ", key, after);
return true;
}
/**
* 释放锁
*
* @param key redis key
*/
private void release(String key) {
Map<String, LockVO> map = lockMap.get();
if (map == null || map.size() == 0 || !map.containsKey(key)) {
return;
}
LockVO vo = map.get(key);
if (vo.afterExpireTime < System.currentTimeMillis()) {
log.debug("release lock {}, because timeout ", key);
map.remove(key);
return;
}
int after = --vo.count;
log.debug("release lock {} {} ", key, after);
if (after > 0) {
return;
}
map.remove(key);
RedisCallback<Boolean> callback = (connection) ->
connection.eval(UNLOCK_LUA.getBytes(StandardCharsets.UTF_8), ReturnType.BOOLEAN, 1,
(key).getBytes(StandardCharsets.UTF_8), vo.lockId.getBytes(StandardCharsets.UTF_8));
redisTemplate.execute(callback);
}
/**
* @param key 锁的key
* @param expire 锁的超时时间
* @param lockId 获取锁后UUID生成的唯一ID
* @return if true success else fail
*/
private boolean tryLock(String key, long expire, String lockId) {
RedisCallback<Boolean> callback = (connection) ->
connection.set((key).getBytes(StandardCharsets.UTF_8),
lockId.getBytes(StandardCharsets.UTF_8), Expiration.seconds(expire), RedisStringCommands.SetOption.SET_IF_ABSENT);
return (Boolean) redisTemplate.execute(callback);
}
private static class LockVO {
/**
* 锁重入的次数
*/
private int count;
/**
* 获取锁后UUID生成的唯一ID
*/
private String lockId;
/**
* 获取锁之前的时间戳
*/
private long beforeExpireTime;
/**
* 获取到锁的时间戳
*/
private long afterExpireTime;
LockVO(int count, String lockId, long beforeExpireTime, long afterExpireTime) {
this.count = count;
this.lockId = lockId;
this.beforeExpireTime = beforeExpireTime;
this.afterExpireTime = afterExpireTime;
}
}
}

View File

@ -0,0 +1,79 @@
package com.qiwenshare.common.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class RedisUtil {
@Resource
RedisTemplate<String, Object> redisTemplate;
/**
* 将值放入缓存
*/
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 字符串取对象
*/
public <T> T getObject(String key) {
Object o = redisTemplate.opsForValue().get(key);
if (o != null) {
return (T) o;
}
return null;
}
/**
* 将值放入缓存并设置时间-
*/
public void set(String key, Object value, long time) {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
redisTemplate.opsForValue().set(key, value);
}
}
/**
* 删除key
*/
public void deleteKey(String key) {
redisTemplate.delete(key);
}
/**
* 创建锁
* @param key 锁的Key
* @param value (随便写毫无意义)
* @param releaseTime 锁过期时间 防止死锁
* @return boolean
*/
public boolean lock(String key, int value, long releaseTime) {
// 尝试获取锁
Boolean boo = redisTemplate.opsForValue().setIfAbsent(key, value, releaseTime, TimeUnit.SECONDS);
// 判断结果
return boo != null && boo;
}
/**
* 根据key删除锁
*/
public void deleteLock(String key) {
// 删除key即可释放锁
deleteKey(key);
}
}

View File

@ -73,12 +73,10 @@
<version>4.13</version>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.qiwenshare</groupId>-->
<!-- <artifactId>file-office</artifactId>-->
<!-- <version>1.0.0-SNAPSHOT</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>

View File

@ -3,6 +3,8 @@ package com.qiwenshare.file;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@ -11,6 +13,11 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableScheduling
//@EnableDiscoveryClient
@EnableTransactionManagement
@ComponentScan(value = "com.qiwenshare", excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = {
}
))
public class FileApplication {
public static void main(String[] args) {

View File

@ -1,6 +1,6 @@
package com.qiwenshare.file.advice;
import com.qiwenshare.common.cbb.ResultCodeEnum;
import com.qiwenshare.common.result.ResultCodeEnum;
import lombok.Data;
/**

View File

@ -1,12 +1,14 @@
package com.qiwenshare.file.advice;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.cbb.ResultCodeEnum;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.result.ResultCodeEnum;
import com.qiwenshare.common.exception.UploadGeneralException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* 该注解为统一异常处理的核心
@ -20,6 +22,7 @@ public class GlobalExceptionHandlerAdvice {
/**-------- 通用异常处理方法 --------**/
@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestResult error(Exception e) {
e.printStackTrace();
log.error("全局异常捕获:" + e);
@ -30,6 +33,7 @@ public class GlobalExceptionHandlerAdvice {
/**-------- 指定异常处理方法 --------**/
@ExceptionHandler(NullPointerException.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestResult error(NullPointerException e) {
e.printStackTrace();
log.error("全局异常捕获:" + e);
@ -38,15 +42,26 @@ public class GlobalExceptionHandlerAdvice {
/**-------- 下标越界处理方法 --------**/
@ExceptionHandler(IndexOutOfBoundsException.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestResult error(IndexOutOfBoundsException e) {
e.printStackTrace();
log.error("全局异常捕获:" + e);
return RestResult.setResult(ResultCodeEnum.INDEX_OUT_OF_BOUNDS);
}
@ExceptionHandler(UploadGeneralException.class)
@ResponseBody
@ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
public RestResult error(UploadGeneralException e) {
e.printStackTrace();
log.error("全局异常捕获:" + e);
return RestResult.setResult(ResultCodeEnum.REQUEST_TIMEOUT);
}
/**-------- 自定义定异常处理方法 --------**/
@ExceptionHandler(CMSException.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestResult error(CMSException e) {
e.printStackTrace();
log.error("全局异常捕获:" + e);

View File

@ -1,6 +1,6 @@
package com.qiwenshare.file.aop;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.IOperationLogService;
import com.qiwenshare.file.api.IUserService;

View File

@ -0,0 +1,8 @@
package com.qiwenshare.file.api;
import com.qiwenshare.file.config.es.FileSearch;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface IElasticSearchService extends ElasticsearchRepository<FileSearch,Long> {
}

View File

@ -19,7 +19,7 @@ public interface IFileService extends IService<FileBean> {
// List<FileBean> selectFileListByPath(FileBean fileBean);
void deleteLocalFile(FileBean fileBean);
// void deleteLocalFile(FileBean fileBean);

View File

@ -1,9 +1,12 @@
package com.qiwenshare.file.api;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.StorageBean;
import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface IFiletransferService {
@ -18,6 +21,8 @@ public interface IFiletransferService {
*/
void uploadFile(HttpServletRequest request, UploadFileDTO UploadFileDto, Long userId);
void downloadFile(HttpServletResponse httpServletResponse, DownloadFileDTO downloadFileDTO);
void deleteFile(FileBean fileBean);
StorageBean selectStorageBean(StorageBean storageBean);
void insertStorageBean(StorageBean storageBean);

View File

@ -21,6 +21,6 @@ public interface IUserFileService extends IService<UserFile> {
Long selectCountNotInExtendNames(List<String> fileNameList, Long beginCount, Long pageCount, long userId);
List<UserFile> selectFileTreeListLikeFilePath(String filePath, long userId);
List<UserFile> selectFilePathTreeByUserId(Long userId);
void deleteUserFile(UserFile userFile, UserBean sessionUserBean);
void deleteUserFile(Long userFileId, Long sessionUserId);
}

View File

@ -1,11 +1,9 @@
package com.qiwenshare.file.api;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.file.domain.UserBean;
import java.util.List;
public interface IUserService extends IService<UserBean> {
UserBean getUserBeanByToken(String token);

View File

@ -0,0 +1,52 @@
package com.qiwenshare.file.config.es;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
@Document(indexName = "filesearch", shards = 1, replicas = 0)
public class FileSearch {
@Id
private long fileSearchId;
@Field(type = FieldType.Long)
private Long fileId;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String fileName;
@Field(type = FieldType.Keyword)
private String timeStampName;
@Field(type = FieldType.Keyword)
private String fileUrl;
@Field(type = FieldType.Long)
private Long fileSize;
@Field(type = FieldType.Integer)
@Deprecated
private Integer isOSS;
@Field(type = FieldType.Integer)
private Integer storageType;
@Field(type = FieldType.Integer)
private Integer pointCount;
@Field(type = FieldType.Keyword)
private String identifier;
@Field(type = FieldType.Long)
private Long userFileId;
@Field(type = FieldType.Long)
private Long userId;
@Field(type = FieldType.Keyword)
private String filePath;
@Field(type = FieldType.Keyword)
private String extendName;
@Field(type = FieldType.Integer)
private Integer isDir;
@Field(type = FieldType.Keyword)
private String uploadTime;
@Field(type = FieldType.Integer)
private Integer deleteFlag;
@Field(type = FieldType.Keyword)
private String deleteTime;
@Field(type = FieldType.Keyword)
private String deleteBatchNum;
}

View File

@ -1,13 +1,16 @@
package com.qiwenshare.file.controller;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.domain.AliyunOSS;
import com.qiwenshare.common.operation.FileOperation;
import com.qiwenshare.common.oss.AliyunOSSRename;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.file.anno.MyLog;
@ -15,14 +18,24 @@ import com.qiwenshare.file.api.IFileService;
import com.qiwenshare.file.api.IRecoveryFileService;
import com.qiwenshare.file.api.IUserFileService;
import com.qiwenshare.file.api.IUserService;
import com.qiwenshare.file.config.QiwenFileConfig;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.config.es.FileSearch;
import com.qiwenshare.file.domain.*;
import com.qiwenshare.file.dto.*;
import com.qiwenshare.file.dto.file.*;
import com.qiwenshare.file.vo.file.FileListVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -54,7 +67,8 @@ public class FileController {
public static final String CURRENT_MODULE = "文件接口";
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
public static long treeid = 0;
@ -86,41 +100,79 @@ public class FileController {
return RestResult.success();
}
@Operation(summary = "文件搜索", description = "文件搜索", tags = {"file"})
@GetMapping(value = "/search")
@MyLog(operation = "文件搜索", module = CURRENT_MODULE)
@ResponseBody
public RestResult<SearchHits<FileSearch>> searchFile(SearchFileDTO searchFileDTO) {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
HighlightBuilder.Field allHighLight = new HighlightBuilder.Field("*").preTags("<span class='keyword'>")
.postTags("</span>");
queryBuilder.withHighlightFields(allHighLight);
//设置分页
int currentPage = (int)searchFileDTO.getCurrentPage() - 1;
int pageCount = (int)(searchFileDTO.getPageCount() == 0 ? 10 : searchFileDTO.getPageCount());
String order = searchFileDTO.getOrder();
Sort.Direction direction = null;
if (searchFileDTO.getDirection() == null) {
direction = Sort.Direction.DESC;
} else if ("asc".equals(searchFileDTO.getDirection())) {
direction = Sort.Direction.ASC;
} else if ("desc".equals(searchFileDTO.getDirection())) {
direction = Sort.Direction.DESC;
} else {
direction = Sort.Direction.DESC;
}
if (order == null) {
queryBuilder.withPageable(PageRequest.of(currentPage, pageCount));
} else {
queryBuilder.withPageable(PageRequest.of(currentPage, pageCount, Sort.by(direction, order)));
}
queryBuilder.withQuery(QueryBuilders.matchQuery("fileName", searchFileDTO.getFileName()));
SearchHits<FileSearch> search = elasticsearchRestTemplate.search(queryBuilder.build(), FileSearch.class);
return RestResult.success().data(search);
}
@Operation(summary = "文件重命名", description = "文件重命名", tags = {"file"})
@RequestMapping(value = "/renamefile", method = RequestMethod.POST)
@MyLog(operation = "文件重命名", module = CURRENT_MODULE)
@ResponseBody
public RestResult<String> renameFile(@RequestBody RenameFileDTO renameFileDto, @RequestHeader("token") String token) {
RestResult<String> restResult = new RestResult<>();
if (!operationCheck(token).getSuccess()){
return operationCheck(token);
}
UserBean sessionUserBean = userService.getUserBeanByToken(token);
UserFile userFile = userFileService.getById(renameFileDto.getUserFileId());
List<UserFile> userFiles = userFileService.selectUserFileByNameAndPath(renameFileDto.getFileName(), renameFileDto.getFilePath(), sessionUserBean.getUserId());
if (userFiles != null && !userFiles.isEmpty()) {
return RestResult.fail().message("同名文件已存在");
}
if (1 == renameFileDto.getIsDir()) {
if (1 == userFile.getIsDir()) {
LambdaUpdateWrapper<UserFile> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.set(UserFile::getFileName, renameFileDto.getFileName())
.set(UserFile::getUploadTime, DateUtil.getCurrentTime())
.eq(UserFile::getUserFileId, renameFileDto.getUserFileId());
userFileService.update(lambdaUpdateWrapper);
userFileService.replaceUserFilePath(renameFileDto.getFilePath() + renameFileDto.getFileName() + "/",
renameFileDto.getFilePath() + renameFileDto.getOldFileName() + "/", sessionUserBean.getUserId());
userFileService.replaceUserFilePath(userFile.getFilePath() + renameFileDto.getFileName() + "/",
userFile.getFilePath() + userFile.getFileName() + "/", sessionUserBean.getUserId());
} else {
if (renameFileDto.getIsOSS() == 1) {
LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(UserFile::getUserFileId, renameFileDto.getUserFileId());
UserFile userFile = userFileService.getOne(lambdaQueryWrapper);
FileBean file = fileService.getById(userFile.getFileId());
if (file.getIsOSS() == 1 || file.getStorageType() == 1) {
// LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// lambdaQueryWrapper.eq(UserFile::getUserFileId, renameFileDto.getUserFileId());
// UserFile userFile = userFileService.getOne(lambdaQueryWrapper);
FileBean file = fileService.getById(userFile.getFileId());
String fileUrl = file.getFileUrl();
String newFileUrl = fileUrl.replace(userFile.getFileName(), renameFileDto.getFileName());
AliyunOSSRename.rename(qiwenFileConfig.getAliyun().getOss(),
rename(qiwenFileConfig.getAliyun().getOss(),
fileUrl.substring(1),
newFileUrl.substring(1));
LambdaUpdateWrapper<FileBean> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
@ -143,12 +195,32 @@ public class FileController {
userFileService.update(lambdaUpdateWrapper);
}
}
return RestResult.success();
}
private void rename(AliyunOSS aliyunOSS, String sourceObjectName, String destinationObjectName) {
String endpoint = aliyunOSS.getEndpoint();
String accessKeyId = aliyunOSS.getAccessKeyId();
String accessKeySecret = aliyunOSS.getAccessKeySecret();
String bucketName = aliyunOSS.getBucketName();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
CopyObjectResult result = ossClient.copyObject(bucketName, sourceObjectName, bucketName, destinationObjectName);
ossClient.deleteObject(bucketName, sourceObjectName);
ObjectMetadata metadata = new ObjectMetadata();
// if ("pdf".equals(FileUtil.getFileType(objectName))) {
// metadata.setContentDisposition("attachment");
// }
// ossClient.putObject(bucketName, objectName, inputStream, metadata);
// 关闭OSSClient
ossClient.shutdown();
}
@Operation(summary = "获取文件列表", description = "用来做前台列表展示", tags = {"file"})
@RequestMapping(value = "/getfilelist", method = RequestMethod.GET)
@ -206,15 +278,9 @@ public class FileController {
List<UserFile> userFiles = JSON.parseArray(batchDeleteFileDto.getFiles(), UserFile.class);
DigestUtils.md5Hex("data");
for (UserFile userFile : userFiles) {
String uuid = UUID.randomUUID().toString();
userFile.setDeleteBatchNum(uuid);
userFileService.deleteUserFile(userFile,sessionUserBean);
RecoveryFile recoveryFile = new RecoveryFile();
recoveryFile.setUserFileId(userFile.getUserFileId());
recoveryFile.setDeleteTime(DateUtil.getCurrentTime());
recoveryFile.setDeleteBatchNum(uuid);
recoveryFileService.save(recoveryFile);
//userFile.setDeleteBatchNum(uuid);
userFileService.deleteUserFile(userFile.getUserFileId(),sessionUserBean.getUserId());
}
return RestResult.success().message("批量删除文件成功");
@ -230,20 +296,16 @@ public class FileController {
return operationCheck(token);
}
String uuid = UUID.randomUUID().toString();
UserBean sessionUserBean = userService.getUserBeanByToken(token);
UserFile userFile = new UserFile();
userFile.setUserFileId(deleteFileDto.getUserFileId());
userFile.setDeleteBatchNum(uuid);
BeanUtil.copyProperties(deleteFileDto, userFile);
userFileService.deleteUserFile(userFile, sessionUserBean);
// String uuid = UUID.randomUUID().toString();
// UserFile userFile = new UserFile();
// userFile.setUserFileId(deleteFileDto.getUserFileId());
//// userFile.setDeleteBatchNum(uuid);
// BeanUtil.copyProperties(deleteFileDto, userFile);
userFileService.deleteUserFile(deleteFileDto.getUserFileId(), sessionUserBean.getUserId());
RecoveryFile recoveryFile = new RecoveryFile();
recoveryFile.setUserFileId(deleteFileDto.getUserFileId());
recoveryFile.setDeleteTime(DateUtil.getCurrentTime());
recoveryFile.setDeleteBatchNum(uuid);
recoveryFileService.save(recoveryFile);
return RestResult.success();
}
@ -309,7 +371,7 @@ public class FileController {
}else{
userFile.setIsDir(0);
userFile.setExtendName(FileUtil.getFileType(totalFileUrl));
userFile.setExtendName(FileUtil.getFileExtendName(totalFileUrl));
userFile.setFileName(FileUtil.getFileNameNotExtend(currentFile.getName()));
tempFileBean.setFileSize(currentFile.length());
tempFileBean.setTimeStampName(FileUtil.getFileNameNotExtend(currentFile.getName()));

View File

@ -1,18 +1,23 @@
package com.qiwenshare.file.controller;
import com.qiwenshare.common.cbb.DateUtil;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.operation.FileOperation;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.IFileService;
import com.qiwenshare.file.api.IFiletransferService;
import com.qiwenshare.file.api.IUserFileService;
import com.qiwenshare.file.api.IUserService;
import com.qiwenshare.file.config.QiwenFileConfig;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.StorageBean;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import com.qiwenshare.file.vo.file.UploadFileVo;
import io.swagger.v3.oas.annotations.Operation;
@ -21,7 +26,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -45,6 +53,8 @@ public class FiletransferController {
IUserService userService;
@Resource
IUserFileService userFileService;
@Autowired
private FastFileStorageClient fastFileStorageClient;
public static final String CURRENT_MODULE = "文件传输接口";
@Operation(summary = "极速上传", description = "校验文件MD5判断文件是否存在如果存在直接上传成功并返回skipUpload=true如果不存在返回skipUpload=false需要再次调用该接口的POST方法", tags = {"filetransfer"})
@ -76,7 +86,7 @@ public class FiletransferController {
userFile.setFilePath(uploadFileDto.getFilePath());
String fileName = uploadFileDto.getFilename();
userFile.setFileName(fileName.substring(0, fileName.lastIndexOf(".")));
userFile.setExtendName(FileUtil.getFileType(fileName));
userFile.setExtendName(FileUtil.getFileExtendName(fileName));
userFile.setDeleteFlag(0);
userFile.setIsDir(0);
userFile.setUploadTime(DateUtil.getCurrentTime());
@ -120,6 +130,81 @@ public class FiletransferController {
}
/**
* 下载文件
*
* @return
*/
@Operation(summary = "下载文件", description = "下载文件接口", tags = {"filetransfer"})
@MyLog(operation = "下载文件", module = CURRENT_MODULE)
@RequestMapping(value = "/downloadfile", method = RequestMethod.GET)
public void downloadFile(HttpServletResponse response, DownloadFileDTO downloadFileDTO) {
filetransferService.downloadFile(response, downloadFileDTO);
}
private void localFileDownload(HttpServletResponse response, FileBean fileBean) {
BufferedInputStream bis = null;
byte[] buffer = new byte[1024];
//设置文件路径
File file = FileOperation.newFile(PathUtil.getStaticPath() + fileBean.getFileUrl());
if (file.exists()) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public void fastFDSDownload(HttpServletResponse response, FileBean fileBean){
String group = fileBean.getFileUrl().substring(0, fileBean.getFileUrl().indexOf("/"));
String path = fileBean.getFileUrl().substring(fileBean.getFileUrl().indexOf("/") + 1);
DownloadByteArray downloadByteArray = new DownloadByteArray();
byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
// // 这里只是为了整合fastdfs所以写死了文件格式需要在上传的时候保存文件名下载的时候使用对应的格式
// response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("sb.xlsx", "UTF-8"));
// response.setCharacterEncoding("UTF-8");
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Operation(summary = "获取存储信息", description = "获取存储信息", tags = {"filetransfer"})
@RequestMapping(value = "/getstorage", method = RequestMethod.GET)
@ResponseBody

View File

@ -3,8 +3,8 @@ package com.qiwenshare.file.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.IRecoveryFileService;

View File

@ -1,11 +1,11 @@
package com.qiwenshare.file.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.util.RandomUtil;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.IShareService;
import com.qiwenshare.file.api.IUserService;
@ -46,7 +46,7 @@ public class ShareController {
public RestResult<ShareFileVO> shareFile(ShareFileDTO shareSecretDTO, @RequestHeader("token") String token) {
ShareFileVO shareSecretVO = new ShareFileVO();
UserBean sessionUserBean = userService.getUserBeanByToken(token);
String extractionCode = RandomUtil.getStringRandom(6);
String extractionCode = RandomUtil.randomNumbers(6);
String uuid = UUID.randomUUID().toString();
Share share = new Share();
BeanUtil.copyProperties(sessionUserBean, share);

View File

@ -1,13 +1,20 @@
package com.qiwenshare.file.controller;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiwenshare.file.api.IElasticSearchService;
import com.qiwenshare.file.config.es.FileSearch;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.service.FileService;
import com.qiwenshare.file.service.FiletransferService;
import com.qiwenshare.file.service.UserFileService;
import com.qiwenshare.file.service.UserService;
import com.qiwenshare.file.vo.file.FileListVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
@ -20,15 +27,18 @@ import java.util.List;
@Controller
public class TaskController {
@Resource
UserFileService userFileService;
@Resource
FileService fileService;
@Resource
UserFileService userFileService;
@Resource
FiletransferService filetransferService;
@Autowired
private IElasticSearchService elasticSearchService;
@Scheduled(cron = "0 0/1 * * * ?")
public void deleteFile() {
log.info("111112");
LambdaQueryWrapper<FileBean> fileBeanLambdaQueryWrapper = new LambdaQueryWrapper<>();
fileBeanLambdaQueryWrapper.eq(FileBean::getPointCount, 0);
@ -36,11 +46,31 @@ public class TaskController {
for (int i = 0; i < fileBeanList.size(); i++) {
FileBean fileBean = fileBeanList.get(i);
log.info("删除本地文件:" + JSON.toJSONString(fileBean));
fileService.deleteLocalFile(fileBean);
filetransferService.deleteFile(fileBean);
fileService.removeById(fileBean.getFileId());
}
fileService.remove(fileBeanLambdaQueryWrapper);
log.info("11111");
}
@Scheduled(fixedRate = 1000 * 60 * 60 * 24)
public void updateElasticSearch() {
UserFile userFile = new UserFile();
try {
elasticSearchService.deleteAll();
} catch (Exception e) {
log.error("删除ES失败:" + e);
}
try {
List<FileListVo> userfiles = userFileService.userFileList(userFile, 0L, 999999L);
for (FileListVo fileListVo : userfiles) {
log.info(JSON.toJSONString(fileListVo));
FileSearch fileSearch = new FileSearch();
BeanUtil.copyProperties(fileListVo, fileSearch);
elasticSearchService.save(fileSearch);
}
} catch (Exception e) {
log.error("更新ES失败:" + e);
}
}
}

View File

@ -2,14 +2,14 @@ package com.qiwenshare.file.controller;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.domain.AliyunOSS;
import com.qiwenshare.common.util.JjwtUtil;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.IUserService;
import com.qiwenshare.file.config.QiwenFileConfig;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.dto.RegisterDTO;
import com.qiwenshare.file.dto.user.RegisterDTO;
import com.qiwenshare.file.vo.user.UserLoginVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;

View File

@ -34,8 +34,12 @@ public class FileBean {
private Long fileSize;
@Column(columnDefinition="int(1)")
@Deprecated
private Integer isOSS;
@Column(columnDefinition="int(1)")
private Integer storageType;
@Column(columnDefinition="int(11)")
private Integer pointCount;

View File

@ -0,0 +1,10 @@
package com.qiwenshare.file.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "下载文件DTO",required = true)
public class DownloadFileDTO {
private Long userFileId;
}

View File

@ -1,15 +0,0 @@
package com.qiwenshare.file.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "用户注册DTO",required = true)
public class RegisterDTO {
@Schema(description = "用户名")
private String username;
@Schema(description = "手机号")
private String telephone;
@Schema(description = "密码")
private String password;
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -8,10 +8,15 @@ import lombok.Data;
public class DeleteFileDTO {
@Schema(description = "用户文件id")
private Long userFileId;
@Schema(description = "文件路径")
@Deprecated
private String filePath;
@Schema(description = "文件名")
@Deprecated
private String fileName;
@Schema(description = "是否是目录")
@Deprecated
private Integer isDir;
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -11,6 +11,7 @@ public class RenameFileDTO {
* 文件路径
*/
@Schema(description = "文件路径")
@Deprecated
private String filePath;
/**
@ -19,9 +20,12 @@ public class RenameFileDTO {
@Schema(description = "文件名")
private String fileName;
@Schema(description = "是否是目录")
@Deprecated
private Integer isDir;
@Schema(description = "旧文件名")
@Deprecated
private String oldFileName;
@Schema(description = "是否是OSS")
@Deprecated
private Integer isOSS;
}

View File

@ -0,0 +1,12 @@
package com.qiwenshare.file.dto.file;
import lombok.Data;
@Data
public class SearchFileDTO {
private String fileName;
private long currentPage;
private long pageCount;
private String order;
private String direction;
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.file.dto;
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

View File

@ -1,6 +1,15 @@
package com.qiwenshare.file.dto.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "用户注册DTO",required = true)
public class RegisterDTO {
@Schema(description = "用户名")
private String username;
@Schema(description = "手机号")
private String telephone;
@Schema(description = "密码")
private String password;
}

View File

@ -1,17 +1,14 @@
package com.qiwenshare.file.service;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.common.operation.FileOperation;
import com.qiwenshare.common.oss.AliyunOSSDelete;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.qiwenshare.file.api.IFileService;
import com.qiwenshare.file.config.QiwenFileConfig;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.mapper.FileMapper;
import com.qiwenshare.file.mapper.UserFileMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@ -28,6 +25,8 @@ public class FileService extends ServiceImpl<FileMapper, FileBean> implements IF
FiletransferService filetransferService;
@Resource
QiwenFileConfig qiwenFileConfig;
@Autowired
private FastFileStorageClient fastFileStorageClient;
// @Override
// public void batchInsertFile(List<FileBean> fileBeanList, Long userId) {
@ -78,21 +77,31 @@ public class FileService extends ServiceImpl<FileMapper, FileBean> implements IF
// .orderByDesc(FileBean::getIsDir);
// return fileMapper.selectList(lambdaQueryWrapper);
// }
@Override
public void deleteLocalFile(FileBean fileBean) {
log.info("删除本地文件:" + JSON.toJSONString(fileBean));
//删除服务器文件
if (fileBean.getFileUrl() != null && fileBean.getFileUrl().indexOf("upload") != -1){
if (fileBean.getIsOSS() != null && fileBean.getIsOSS() == 1) {
AliyunOSSDelete.deleteObject(qiwenFileConfig.getAliyun().getOss(), fileBean.getFileUrl().substring(1));
} else {
FileOperation.deleteFile(PathUtil.getStaticPath() + fileBean.getFileUrl());
if (FileUtil.isImageFile(FileUtil.getFileType(fileBean.getFileUrl()))) {
FileOperation.deleteFile(PathUtil.getStaticPath() + fileBean.getFileUrl().replace(fileBean.getTimeStampName(), fileBean.getTimeStampName() + "_min"));
}
}
}
}
// @Override
// public void deleteLocalFile(FileBean fileBean) {
// log.info("删除本地文件:" + JSON.toJSONString(fileBean));
// //删除服务器文件
// if (fileBean.getFileUrl() != null && fileBean.getFileUrl().indexOf("upload") != -1){
// if (fileBean.getIsOSS() != null && fileBean.getIsOSS() == 1) {
// AliyunOSSDelete.deleteObject(qiwenFileConfig.getAliyun().getOss(), fileBean.getFileUrl().substring(1));
// } else if (fileBean.getStorageType() == 0) {
// FileOperation.deleteFile(PathUtil.getStaticPath() + fileBean.getFileUrl());
// if (FileUtil.isImageFile(FileUtil.getFileExtendName(fileBean.getFileUrl()))) {
// FileOperation.deleteFile(PathUtil.getStaticPath() + fileBean.getFileUrl().replace(fileBean.getTimeStampName(), fileBean.getTimeStampName() + "_min"));
// }
// } else if (fileBean.getStorageType() == 1) {
// AliyunOSSDelete.deleteObject(qiwenFileConfig.getAliyun().getOss(), fileBean.getFileUrl().substring(1));
// } else if (fileBean.getStorageType() == 2){
// fastFileStorageClient.deleteFile(fileBean.getFileUrl());
//
// } else {
// FileOperation.deleteFile(PathUtil.getStaticPath() + fileBean.getFileUrl());
// if (FileUtil.isImageFile(FileUtil.getFileExtendName(fileBean.getFileUrl()))) {
// FileOperation.deleteFile(PathUtil.getStaticPath() + fileBean.getFileUrl().replace(fileBean.getTimeStampName(), fileBean.getTimeStampName() + "_min"));
// }
// }
// }
// }

View File

@ -1,23 +1,30 @@
package com.qiwenshare.file.service;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.domain.DeleteFile;
import com.qiwenshare.common.domain.DownloadFile;
import com.qiwenshare.common.domain.UploadFile;
import com.qiwenshare.common.upload.factory.AliyunOSSUploaderFactory;
import com.qiwenshare.common.upload.factory.ChunkUploaderFactory;
import com.qiwenshare.common.upload.Uploader;
//import com.qiwenshare.common.factory.FileOperationFactory;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.operation.download.Downloader;
import com.qiwenshare.common.factory.FileOperationFactory;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.file.api.IFiletransferService;
import com.qiwenshare.common.domain.AliyunOSS;
import com.qiwenshare.file.config.QiwenFileConfig;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import com.qiwenshare.file.mapper.FileMapper;
import com.qiwenshare.file.domain.FileBean;
@ -34,19 +41,23 @@ public class FiletransferService implements IFiletransferService {
StorageMapper storageMapper;
@Resource
FileMapper fileMapper;
@Resource
QiwenFileConfig qiwenFileConfig;
@Resource
UserFileMapper userFileMapper;
@Resource
FileOperationFactory fastDFSOperationFactory;
@Resource
FileOperationFactory aliyunOSSOperationFactory;
@Resource
FileOperationFactory localStorageOperationFactory;
@Override
public void uploadFile(HttpServletRequest request, UploadFileDTO UploadFileDto, Long userId) {
AliyunOSS oss = qiwenFileConfig.getAliyun().getOss();
request.setAttribute("oss", oss);
Uploader uploader;
Uploader uploader = null;
UploadFile uploadFile = new UploadFile();
uploadFile.setChunkNumber(UploadFileDto.getChunkNumber());
uploadFile.setChunkSize(UploadFileDto.getChunkSize());
@ -54,13 +65,18 @@ public class FiletransferService implements IFiletransferService {
uploadFile.setIdentifier(UploadFileDto.getIdentifier());
uploadFile.setTotalSize(UploadFileDto.getTotalSize());
uploadFile.setCurrentChunkSize(UploadFileDto.getCurrentChunkSize());
if (oss.isEnabled()) {
uploader = new AliyunOSSUploaderFactory().getUploader(uploadFile);
} else {
uploader = new ChunkUploaderFactory().getUploader(uploadFile);
synchronized (FiletransferService.class) {
String storageType = qiwenFileConfig.getStorageType();
if ("0".equals(storageType)) {
uploader = localStorageOperationFactory.getUploader();
} else if ("1".equals(storageType)) {
uploader = aliyunOSSOperationFactory.getUploader();
} else if ("2".equals(storageType)) {
uploader = fastDFSOperationFactory.getUploader();
}
}
List<UploadFile> uploadFileList = uploader.upload(request);
List<UploadFile> uploadFileList = uploader.upload(request, uploadFile);
for (int i = 0; i < uploadFileList.size(); i++){
uploadFile = uploadFileList.get(i);
FileBean fileBean = new FileBean();
@ -71,7 +87,7 @@ public class FiletransferService implements IFiletransferService {
fileBean.setFileSize(uploadFile.getFileSize());
//fileBean.setUploadTime(DateUtil.getCurrentTime());
fileBean.setIsOSS(uploadFile.getIsOSS());
fileBean.setStorageType(uploadFile.getStorageType());
fileBean.setPointCount(1);
fileMapper.insert(fileBean);
UserFile userFile = new UserFile();
@ -103,6 +119,55 @@ public class FiletransferService implements IFiletransferService {
}
}
@Override
public void downloadFile(HttpServletResponse httpServletResponse, DownloadFileDTO downloadFileDTO) {
UserFile userFile = userFileMapper.selectById(downloadFileDTO.getUserFileId());
String fileName = userFile.getFileName() + "." + userFile.getExtendName();
try {
fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
httpServletResponse.setContentType("application/force-download");// 设置强制下载不打开
httpServletResponse.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
FileBean fileBean = fileMapper.selectById(userFile.getFileId());
Downloader downloader = null;
if (fileBean.getIsOSS() != null && fileBean.getIsOSS() == 1) {
downloader = aliyunOSSOperationFactory.getDownloader();
} else if (fileBean.getStorageType() == 0) {
downloader = localStorageOperationFactory.getDownloader();
} else if (fileBean.getStorageType() == 1) {
downloader = aliyunOSSOperationFactory.getDownloader();
} else if (fileBean.getStorageType() == 2) {
downloader = fastDFSOperationFactory.getDownloader();
}
DownloadFile uploadFile = new DownloadFile();
uploadFile.setFileUrl(fileBean.getFileUrl());
uploadFile.setTimeStampName(fileBean.getTimeStampName());
downloader.download(httpServletResponse, uploadFile);
}
@Override
public void deleteFile(FileBean fileBean) {
Deleter deleter = null;
if (fileBean.getIsOSS() != null && fileBean.getIsOSS() == 1) {
deleter = aliyunOSSOperationFactory.getDeleter();
} else if (fileBean.getStorageType() == 0) {
deleter = localStorageOperationFactory.getDeleter();
} else if (fileBean.getStorageType() == 1) {
deleter = aliyunOSSOperationFactory.getDeleter();
} else if (fileBean.getStorageType() == 2) {
deleter = fastDFSOperationFactory.getDeleter();
}
DeleteFile deleteFile = new DeleteFile();
deleteFile.setFileUrl(fileBean.getFileUrl());
deleteFile.setTimeStampName(fileBean.getTimeStampName());
deleter.delete(deleteFile);
}
@Override
public StorageBean selectStorageBean(StorageBean storageBean) {
LambdaQueryWrapper<StorageBean> lambdaQueryWrapper = new LambdaQueryWrapper<>();

View File

@ -1,13 +1,14 @@
package com.qiwenshare.file.service;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.file.api.IRecoveryFileService;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.RecoveryFile;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.mapper.FileMapper;
import com.qiwenshare.file.mapper.RecoveryFileMapper;
@ -56,6 +57,67 @@ public class RecoveryFileService extends ServiceImpl<RecoveryFileMapper, Recove
}
public void restorefile(String deleteBatchNum, String filePath, Long sessionUserId) {
LambdaUpdateWrapper<UserFile> userFileLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
userFileLambdaUpdateWrapper.set(UserFile::getDeleteFlag, 0)
.set(UserFile::getDeleteBatchNum, "")
.eq(UserFile::getDeleteBatchNum, deleteBatchNum);
userFileMapper.update(null, userFileLambdaUpdateWrapper);
String parentFilePath = PathUtil.getParentPath(filePath);
while(parentFilePath.indexOf("/") != -1) {
String fileName = parentFilePath.substring(parentFilePath.lastIndexOf("/") + 1);
parentFilePath = PathUtil.getParentPath(parentFilePath);
LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(UserFile::getFilePath, parentFilePath + "/")
.eq(UserFile::getDeleteFlag, 0)
.eq(UserFile::getUserId, sessionUserId);
List<UserFile> userFileList = userFileMapper.selectList(lambdaQueryWrapper);
if (userFileList.size() == 0) {
UserFile userFile = new UserFile();
userFile.setUserId(sessionUserId);
userFile.setFileName(fileName);
userFile.setFilePath(parentFilePath + "/");
userFile.setDeleteFlag(0);
userFile.setIsDir(1);
userFile.setUploadTime(DateUtil.getCurrentTime());
userFileMapper.insert(userFile);
}
}
LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(UserFile::getFileName, UserFile::getFilePath)
.likeRight(UserFile::getFilePath, filePath)
.eq(UserFile::getIsDir, 1)
.eq(UserFile::getDeleteFlag, 0)
.groupBy(UserFile::getFilePath, UserFile::getFileName)
.having("count(fileName) >= 2");
List<UserFile> repeatList = userFileMapper.selectList(lambdaQueryWrapper);
for (UserFile userFile : repeatList) {
LambdaQueryWrapper<UserFile> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
lambdaQueryWrapper1.eq(UserFile::getFilePath, userFile.getFilePath())
.eq(UserFile::getFileName, userFile.getFileName())
.eq(UserFile::getDeleteFlag, "0");
List<UserFile> userFiles = userFileMapper.selectList(lambdaQueryWrapper1);
log.info("重复的文件:" + JSON.toJSONString(userFiles));
for (int i = 0; i < userFiles.size() - 1; i ++) {
log.info("删除文件:" + JSON.toJSONString(userFiles.get(i)));
userFileMapper.deleteById(userFiles.get(i).getUserFileId());
}
}
log.info(JSON.toJSONString(repeatList));
LambdaQueryWrapper<RecoveryFile> recoveryFileServiceLambdaQueryWrapper = new LambdaQueryWrapper<>();
recoveryFileServiceLambdaQueryWrapper.eq(RecoveryFile::getDeleteBatchNum, deleteBatchNum);
recoveryFileMapper.delete(recoveryFileServiceLambdaQueryWrapper);
}
private void updateFilePointCountByBatchNum(String deleteBatchNum) {

View File

@ -3,13 +3,14 @@ package com.qiwenshare.file.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.file.api.IUserFileService;
import com.qiwenshare.file.config.QiwenFileConfig;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.domain.RecoveryFile;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.mapper.FileMapper;
import com.qiwenshare.file.mapper.RecoveryFileMapper;
import com.qiwenshare.file.mapper.UserFileMapper;
import com.qiwenshare.file.vo.file.FileListVo;
import lombok.extern.slf4j.Slf4j;
@ -17,7 +18,7 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@ -29,6 +30,8 @@ public class UserFileService extends ServiceImpl<UserFileMapper, UserFile> impl
@Resource
FileMapper fileMapper;
@Resource
RecoveryFileMapper recoveryFileMapper;
@Resource
FiletransferService filetransferService;
@Resource
QiwenFileConfig qiwenFileConfig;
@ -56,7 +59,53 @@ public class UserFileService extends ServiceImpl<UserFileMapper, UserFile> impl
return userFileMapper.userFileList(userFile, beginCount, pageCount);
}
// public void renameUserFile(Long userFileId, String newFileName, Long userId) {
// UserFile userFile = userFileMapper.selectById(userFileId);
// if (1 == userFile.getIsDir()) {
// LambdaUpdateWrapper<UserFile> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// lambdaUpdateWrapper.set(UserFile::getFileName, newFileName)
// .set(UserFile::getUploadTime, DateUtil.getCurrentTime())
// .eq(UserFile::getUserFileId, userFile.getUserFileId());
// userFileMapper.update(null, lambdaUpdateWrapper);
// replaceUserFilePath(userFile.getFilePath() + newFileName + "/",
// userFile.getFilePath() + userFile.getFileName() + "/", userId);
// } else {
// FileBean fileBean = fileMapper.selectById(userFile.getFileId());
// if (fileBean.getIsOSS() == 1) {
//// LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//// lambdaQueryWrapper.eq(UserFile::getUserFileId, renameFileDto.getUserFileId());
//// UserFile userFile = userFileService.getOne(lambdaQueryWrapper);
////
//// FileBean file = fileService.getById(userFile.getFileId());
// String fileUrl = fileBean.getFileUrl();
// String newFileUrl = fileUrl.replace(userFile.getFileName(), newFileName);
//
// AliyunOSSRename.rename(qiwenFileConfig.getAliyun().getOss(),
// fileUrl.substring(1),
// newFileUrl.substring(1));
// LambdaUpdateWrapper<FileBean> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// lambdaUpdateWrapper
// .set(FileBean::getFileUrl, newFileUrl)
// .eq(FileBean::getFileId, fileBean.getFileId());
// fileMapper.update(null, lambdaUpdateWrapper);
//
// LambdaUpdateWrapper<UserFile> userFileLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// userFileLambdaUpdateWrapper
// .set(UserFile::getFileName, newFileName)
// .set(UserFile::getUploadTime, DateUtil.getCurrentTime())
// .eq(UserFile::getUserFileId, userFileId);
// userFileMapper.update(null, userFileLambdaUpdateWrapper);
// } else {
// LambdaUpdateWrapper<UserFile> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// lambdaUpdateWrapper.set(UserFile::getFileName, newFileName)
// .set(UserFile::getUploadTime, DateUtil.getCurrentTime())
// .eq(UserFile::getUserFileId, userFileId);
// userFileMapper.update(null, lambdaUpdateWrapper);
// }
//
//
// }
// }
@Override
public void updateFilepathByFilepath(String oldfilePath, String newfilePath, String fileName, String extendName) {
@ -131,37 +180,43 @@ public class UserFileService extends ServiceImpl<UserFileMapper, UserFile> impl
@Override
public void deleteUserFile(UserFile userFile, UserBean sessionUserBean) {
public void deleteUserFile(Long userFileId, Long sessionUserId) {
// UserFile userFile
UserFile userFile = userFileMapper.selectById(userFileId);
String uuid = UUID.randomUUID().toString();
if (userFile.getIsDir() == 1) {
LambdaUpdateWrapper<UserFile> userFileLambdaUpdateWrapper = new LambdaUpdateWrapper<UserFile>();
userFileLambdaUpdateWrapper.set(UserFile::getDeleteFlag, 1)
.set(UserFile::getDeleteBatchNum, userFile.getDeleteBatchNum())
.set(UserFile::getDeleteBatchNum, uuid)
.set(UserFile::getDeleteTime, DateUtil.getCurrentTime())
.eq(UserFile::getUserFileId, userFile.getUserFileId());
.eq(UserFile::getUserFileId, userFileId);
userFileMapper.update(null, userFileLambdaUpdateWrapper);
String filePath = userFile.getFilePath() + userFile.getFileName() + "/";
updateFileDeleteStateByFilePath(filePath, userFile.getDeleteBatchNum(), sessionUserBean.getUserId());
updateFileDeleteStateByFilePath(filePath, userFile.getDeleteBatchNum(), sessionUserId);
}else{
UserFile userFileTemp = userFileMapper.selectById(userFile.getUserFileId());
UserFile userFileTemp = userFileMapper.selectById(userFileId);
FileBean fileBean = fileMapper.selectById(userFileTemp.getFileId());
LambdaUpdateWrapper<UserFile> userFileLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
userFileLambdaUpdateWrapper.set(UserFile::getDeleteFlag, 1)
.set(UserFile::getDeleteTime, DateUtil.getCurrentTime())
.set(UserFile::getDeleteBatchNum, userFile.getDeleteBatchNum())
.set(UserFile::getDeleteBatchNum, uuid)
.eq(UserFile::getUserFileId, userFileTemp.getUserFileId());
userFileMapper.update(null, userFileLambdaUpdateWrapper);
// LambdaUpdateWrapper<FileBean> fileBeanLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// fileBeanLambdaUpdateWrapper.set(FileBean::getPointCount, fileBean.getPointCount() -1)
// .eq(FileBean::getFileId, fileBean.getFileId());
}
RecoveryFile recoveryFile = new RecoveryFile();
recoveryFile.setUserFileId(userFileId);
recoveryFile.setDeleteTime(DateUtil.getCurrentTime());
recoveryFile.setDeleteBatchNum(uuid);
recoveryFileMapper.insert(recoveryFile);
}
private void updateFileDeleteStateByFilePath(String filePath, String deleteBatchNum, Long userId) {

View File

@ -3,8 +3,8 @@ package com.qiwenshare.file.service;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.cbb.RestResult;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.JjwtUtil;
import com.qiwenshare.common.util.PasswordUtil;
import com.qiwenshare.file.api.IUserService;
@ -15,8 +15,6 @@ import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

View File

@ -1,10 +1,9 @@
package com.qiwenshare.file.util;
import com.qiwenshare.common.cbb.CollectUtil;
import com.qiwenshare.common.cbb.DateUtil;
import com.qiwenshare.common.util.CollectUtil;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.file.domain.OperationLogBean;
import com.qiwenshare.file.domain.UserBean;
import org.apache.shiro.SecurityUtils;
import javax.servlet.http.HttpServletRequest;

View File

@ -12,8 +12,11 @@ public class FileListVo {
private Long fileSize;
@Deprecated
private Integer isOSS;
private Integer storageType;
private Integer pointCount;
private String identifier;

View File

@ -15,7 +15,10 @@ public class ShareFileListVO {
@Schema(description="文件大小")
private Long fileSize;
@Schema(description="是否sso存储")
@Deprecated
private Integer isOSS;
@Schema(description="存储类型")
private Integer storageType;
//
// private Long userFileId;
//

View File

@ -49,11 +49,13 @@ mybatis-plus.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis-plus.configuration.map-underscore-to-camel-case=false
mybatis-plus.global-config.banner=false
qiwen-file.remote-login=false
qiwen-file.share-mode=false
qiwen-file.storage-type=0
qiwen-file.cache-mode=0
#是否启用阿里云oss
qiwen-file.aliyun.oss.enabled=false
#qiwen-file.aliyun.oss.enabled=false
#阿里云oss基本配置
qiwen-file.aliyun.oss.endpoint=
qiwen-file.aliyun.oss.access-key-id=
@ -62,3 +64,34 @@ qiwen-file.aliyun.oss.bucket-name=
#阿里云oss绑定域名
qiwen-file.aliyun.oss.domain=
fdfs.so-timeout=1501
fdfs.connect-timeout=601
fdfs.thumb-image.width=150
fdfs.thumb-image.height=150
fdfs.tracker-list=121.89.222.103:22122
# Redis数据库索引默认为0
spring.redis.database=0
# Redis服务器地址
spring.redis.host=123.56.9.174
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码默认为空
spring.redis.password=ma123456
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=10000
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=30
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=10
#连接超时时间(毫秒)
spring.redis.timeout=5000
spring.data.elasticsearch.client.reactive.endpoints=127.0.0.1:9200
spring.elasticsearch.rest.uris=127.0.0.1:9200

View File

@ -30,9 +30,7 @@
limit #{beginCount}, #{pageCount}
</select>
<select id="selectFileByExtendName" parameterType="com.qiwenshare.file.domain.UserFile" resultType="com.qiwenshare.file.vo.file.FileListVo">
select * from userfile
<sql id="selectByExtendName" >
left join file on file.fileId = userfile.fileId
where extendName in
<foreach collection="fileNameList" open="(" close=")" separator="," item="fileName" >
@ -40,41 +38,36 @@
</foreach>
and userId = #{userId}
and deleteFlag = 0
</sql>
<sql id="selectByNotExtendName">
left join file on file.fileId = userfile.fileId
where extendName not in
<foreach collection="fileNameList" open="(" close=")" separator="," item="fileName" >
#{fileName}
</foreach>
and userId = #{userId}
and deleteFlag = 0
</sql>
<select id="selectFileByExtendName" parameterType="com.qiwenshare.file.domain.UserFile" resultType="com.qiwenshare.file.vo.file.FileListVo">
select * from userfile
<include refid="selectByExtendName"></include>
limit #{beginCount}, #{pageCount}
</select>
<select id="selectCountByExtendName" parameterType="com.qiwenshare.file.domain.UserFile" resultType="java.lang.Long">
select count(*) from userfile
left join file on file.fileId = userfile.fileId
where extendName in
<foreach collection="fileNameList" open="(" close=")" separator="," item="fileName" >
#{fileName}
</foreach>
and userId = #{userId}
and deleteFlag = 0
<include refid="selectByExtendName"></include>
</select>
<select id="selectFileNotInExtendNames" parameterType="com.qiwenshare.file.domain.UserFile" resultType="com.qiwenshare.file.vo.file.FileListVo">
select * from userfile
left join file on file.fileId = userfile.fileId
where extendName not in
<foreach collection="fileNameList" open="(" close=")" separator="," item="fileName" >
#{fileName}
</foreach>
and userId = #{userId}
and deleteFlag = 0
<include refid="selectByNotExtendName"></include>
limit #{beginCount}, #{pageCount}
</select>
<select id="selectCountNotInExtendNames" parameterType="com.qiwenshare.file.domain.UserFile" resultType="java.lang.Long">
select count(*) from userfile
left join file on file.fileId = userfile.fileId
where extendName not in
<foreach collection="fileNameList" open="(" close=")" separator="," item="fileName" >
#{fileName}
</foreach>
and userId = #{userId}
and deleteFlag = 0
<include refid="selectByNotExtendName"></include>
</select>