代码优化

This commit is contained in:
马超 2021-05-29 22:03:42 +08:00
parent adc841020e
commit 748cb763ef
161 changed files with 293 additions and 3349 deletions

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.qiwenshare</groupId>
<artifactId>file</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.qiwenshare</groupId>
<artifactId>file-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>7.4.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>commons-fileupload</groupId>-->
<!-- <artifactId>commons-fileupload</artifactId>-->
<!-- <version>1.3.3</version>-->
<!-- </dependency>-->
<!--图片压缩-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.13</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<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>
</project>

View File

@ -1,11 +0,0 @@
package com.qiwenshare.common.config;
import com.qiwenshare.common.domain.AliyunOSS;
import lombok.Data;
@Data
public class AliyunConfig {
private AliyunOSS oss = new AliyunOSS();
}

View File

@ -1,21 +0,0 @@
package com.qiwenshare.common.config;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import com.qiwenshare.common.util.PropertiesUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@Configuration
public class PropertiesConfig {
@Resource
private Environment env;
@PostConstruct
public void setProperties() {
PropertiesUtil.setEnvironment(env);
}
}

View File

@ -1,20 +0,0 @@
package com.qiwenshare.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "qiwen-file")
public class QiwenFileConfig {
private boolean shareMode;
private String storageType;
private String cacheMode;
private String localStoragePath;
private AliyunConfig aliyun = new AliyunConfig();
}

View File

@ -1,10 +0,0 @@
package com.qiwenshare.common.constant;
public class FileConstant {
/**
* 路径分隔符
*/
public static final String pathSeparator = "/";
public static final int deleteFileRandomSize = 999999;
}

View File

@ -1,14 +0,0 @@
package com.qiwenshare.common.domain;
import lombok.Data;
@Data
public class AliyunOSS {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
private String objectName;
private String domain;
}

View File

@ -1,18 +0,0 @@
package com.qiwenshare.common.exception;
public class NotLoginException extends RuntimeException{
public NotLoginException() {
super("未登录");
}
public NotLoginException(Throwable cause) {
super("未登录", cause);
}
public NotLoginException(String message) {
super(message);
}
public NotLoginException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,7 +0,0 @@
package com.qiwenshare.common.exception;
public class NotSameFileExpection extends Exception {
public NotSameFileExpection() {
super("File MD5 Different");
}
}

View File

@ -1,12 +0,0 @@
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

@ -1,16 +0,0 @@
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

@ -1,39 +0,0 @@
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

@ -1,38 +0,0 @@
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

@ -1,11 +0,0 @@
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

@ -1,38 +0,0 @@
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

@ -1,425 +0,0 @@
package com.qiwenshare.common.operation;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* 文件操作
*/
@Slf4j
public class FileOperation {
private static Logger logger = LoggerFactory.getLogger(FileOperation.class);
private static Executor executor = Executors.newFixedThreadPool(20);
/**
* 创建文件
*
* @param fileUrl 文件路径
* @return 新文件
*/
public static File newFile(String fileUrl) {
File file = new File(fileUrl);
return file;
}
/**
* 删除文件
*
* @param file 文件
* @return 是否删除成功
*/
public static boolean deleteFile(File file) {
if (file == null) {
return false;
}
if (!file.exists()) {
return false;
}
if (file.isFile()) {
return file.delete();
} else {
for (File newfile : file.listFiles()) {
deleteFile(newfile);
}
}
return file.delete();
}
/**
* 删除文件
*
* @param fileUrl 文件路径
* @return 删除是否成功
*/
public static boolean deleteFile(String fileUrl) {
File file = newFile(fileUrl);
return deleteFile(file);
}
/**
* 得到文件大小
*
* @param fileUrl 文件路径
* @return 文件大小
*/
public static long getFileSize(String fileUrl) {
File file = newFile(fileUrl);
if (file.exists()) {
return file.length();
}
return 0;
}
/**
* 得到文件大小
*
* @param file 文件
* @return 文件大小
*/
public static long getFileSize(File file) {
if (file == null) {
return 0;
}
return file.length();
}
/**
* 创建目录
*
* @param file 文件
* @return 是否创建成功
*/
public static boolean mkdir(File file) {
if (file == null) {
return false;
}
if (file.exists()) {
return true;
}
return file.mkdirs();
}
/**
* 创建目录
*
* @param fileUrl 文件路径
* @return 是否创建成功
*/
public static boolean mkdir(String fileUrl) {
if (fileUrl == null) {
return false;
}
File file = newFile(fileUrl);
if (file.exists()) {
return true;
}
return file.mkdirs();
}
/**
* 拷贝文件
*
* @param fileInputStream 文件输入流
* @param fileOutputStream 文件输出流
* @throws IOException io异常
*/
public static void copyFile(FileInputStream fileInputStream, FileOutputStream fileOutputStream) throws IOException {
try {
byte[] buf = new byte[4096]; //8k的缓冲区
int len = fileInputStream.read(buf); //数据在buf中len代表向buf中放了多少个字节的数据-1代表读不到
while (len != -1) {
fileOutputStream.write(buf, 0, len); //读多少个字节写多少个字节
len = fileInputStream.read(buf);
}
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 拷贝文件
*
* @param src 源文件
* @param dest 目的文件
* @throws IOException io异常
*/
public static void copyFile(File src, File dest) throws IOException {
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dest);
copyFile(in, out);
}
/**
* 拷贝文件
*
* @param srcUrl 源路径
* @param destUrl 目的路径
* @throws IOException io异常
*/
public static void copyFile(String srcUrl, String destUrl) throws IOException {
if (srcUrl == null || destUrl == null) {
return;
}
File srcFile = newFile(srcUrl);
File descFile = newFile(destUrl);
copyFile(srcFile, descFile);
}
/**
* 文件解压缩
*
* @param sourceFile 需要解压的文件
* @param destDirPath 目的路径
* @return 解压目录列表
*/
public static List<String> unzip(File sourceFile, String destDirPath) {
ZipFile zipFile = null;
Set<String> set = new HashSet<String>();
// set.add("/");
List<String> fileEntryNameList = new ArrayList<>();
try {
zipFile = new ZipFile(sourceFile, Charset.forName("GBK"));
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String[] nameStrArr = entry.getName().split("/");
String nameStr = "/";
for (int i = 0; i < nameStrArr.length; i++) {
if (!"".equals(nameStrArr[i])) {
nameStr = nameStr + "/" + nameStrArr[i];
set.add(nameStr);
}
}
logger.info("解压" + entry.getName());
String zipPath = "/" + entry.getName();
fileEntryNameList.add(zipPath);
//如果是文件夹就创建个文件夹
if (entry.isDirectory()) {
String dirPath = destDirPath + File.separator + entry.getName();
File dir = FileOperation.newFile(dirPath);
dir.mkdir();
} else {
//如果是文件就先创建一个文件然后用io流把内容拷过去
File targetFile = new File(destDirPath + "/" + entry.getName());
// 保证这个文件的父文件夹必须要存在
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
targetFile.createNewFile();
// 将压缩文件内容写入到这个文件中
InputStream is = null;
FileOutputStream fos = null;
try {
is = zipFile.getInputStream(entry);
fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[2048];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (Exception e) {
// 关流顺序先打开的后关闭
if (fos != null) {
try {
fos.close();
} catch (Exception e1) {
log.error("关闭流失败:" + e1);
}
}
if (is != null) {
try {
is.close();
} catch (Exception e2) {
log.error("关闭流失败:" + e2);
}
}
}
}
}
} catch (Exception e) {
throw new RuntimeException("unzip error from ZipUtils", e);
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
for (String zipPath : fileEntryNameList) {
executor.execute(new Runnable() {
@Override
public void run() {
if (FileUtil.isImageFile(FileUtil.getFileExtendName(zipPath))) {
File file = new File(destDirPath + zipPath);
File minFile = new File(destDirPath + FileUtil.getFileNameNotExtend(zipPath) + "_min." + FileUtil.getFileExtendName(zipPath));
try {
ImageOperation.thumbnailsImage(file, minFile, 300);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
List<String> res = new ArrayList<>(set);
return res;
}
/**
* 解压rar
*
* @param sourceFile 需要解压的文件
* @param destDirPath 目的路径
* @throws Exception
*/
public static List<String> unrar(File sourceFile, String destDirPath) throws Exception {
File destDir = new File(destDirPath);
Set<String> set = new HashSet<String>();
Archive archive = null;
FileOutputStream fos = null;
System.out.println("Starting 开始解压...");
try {
archive = new Archive(sourceFile);
FileHeader fh = archive.nextFileHeader();
int count = 0;
File destFileName = null;
while (fh != null) {
set.add("/" + fh.getFileName());
System.out.println((++count) + ") " + fh.getFileName());
String compressFileName = fh.getFileName().trim();
destFileName = new File(destDir.getAbsolutePath() + "/" + compressFileName);
if (fh.isDirectory()) {
if (!destFileName.exists()) {
destFileName.mkdirs();
}
fh = archive.nextFileHeader();
continue;
}
if (!destFileName.getParentFile().exists()) {
destFileName.getParentFile().mkdirs();
}
fos = new FileOutputStream(destFileName);
archive.extractFile(fh, fos);
fos.close();
fos = null;
fh = archive.nextFileHeader();
}
archive.close();
archive = null;
System.out.println("Finished 解压完成!");
} catch (Exception e) {
throw e;
} finally {
if (fos != null) {
try {
fos.close();
} catch (Exception e) {
log.error("关闭流失败:" + e.getMessage());
}
}
if (archive != null) {
try {
archive.close();
} catch (Exception e) {
log.error("关闭流失败:" + e.getMessage());
}
}
}
for (String zipPath : set) {
executor.execute(new Runnable() {
@Override
public void run() {
if (FileUtil.isImageFile(FileUtil.getFileExtendName(zipPath))) {
File file = new File(destDirPath + zipPath);
File minFile = new File(destDirPath + FileUtil.getFileNameNotExtend(zipPath) + "_min." + FileUtil.getFileExtendName(zipPath));
try {
ImageOperation.thumbnailsImage(file, minFile, 300);
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
List<String> res = new ArrayList<>(set);
return res;
}
public static long deleteFileFromDisk(String fileurl) {
String fileUrl = PathUtil.getStaticPath() + fileurl;
String extendName = FileUtil.getFileExtendName(fileUrl);
String minFileUrl = fileUrl.replace("." + extendName, "_min." + extendName);
long filesize = getFileSize(fileUrl);
FileOperation.deleteFile(fileUrl);
FileOperation.deleteFile(minFileUrl);
return filesize;
}
}

View File

@ -1,43 +0,0 @@
package com.qiwenshare.common.operation;
import net.coobird.thumbnailator.Thumbnails;
import java.io.File;
import java.io.IOException;
public class ImageOperation {
/**
* 左旋
* @param inFile 源文件
* @param outFile 目的文件
* @param angle 角度
* @throws IOException io异常
*/
public static void leftTotation(File inFile, File outFile, int angle) throws IOException {
Thumbnails.of(inFile).scale(1).outputQuality(1).rotate(-angle).toFile(outFile);
}
/**
* 右旋
* @param inFile 源文件
* @param outFile 目的文件
* @param angle 角度
* @throws IOException io异常
*/
public static void rightTotation(File inFile, File outFile, int angle) throws IOException {
Thumbnails.of(inFile).scale(1).outputQuality(1).rotate(angle).toFile(outFile);
}
/**
* 压缩
* @param inFile 源文件
* @param outFile 目的文件
* @throws IOException io异常
*/
public static void thumbnailsImage(File inFile, File outFile, int imageSize) throws IOException {
Thumbnails.of(inFile).size(imageSize, imageSize)
.toFile(outFile);
}
}

View File

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

View File

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

View File

@ -1,31 +0,0 @@
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.operation.delete.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) {
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

@ -1,17 +0,0 @@
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.operation.delete.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().replace("M00", "group1"));
}
}

View File

@ -1,19 +0,0 @@
package com.qiwenshare.common.operation.delete.product;
import com.qiwenshare.common.operation.delete.Deleter;
import com.qiwenshare.common.operation.delete.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

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

View File

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

View File

@ -1,72 +0,0 @@
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.operation.download.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.getFileUrl().substring(1));
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();
}
@Override
public InputStream getInputStream(DownloadFile downloadFile) {
OSS ossClient = createOSSClient(qiwenFileConfig.getAliyun().getOss());
OSSObject ossObject = ossClient.getObject(qiwenFileConfig.getAliyun().getOss().getBucketName(),
downloadFile.getFileUrl().substring(1));
InputStream inputStream = ossObject.getObjectContent();
return inputStream;
}
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

@ -1,57 +0,0 @@
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.operation.download.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.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@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("/"));
group = "group1";
String path = downloadFile.getFileUrl().substring(downloadFile.getFileUrl().indexOf("/") + 1);
DownloadByteArray downloadByteArray = new DownloadByteArray();
ServletOutputStream outputStream = null;
try {
outputStream = httpServletResponse.getOutputStream();
byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public InputStream getInputStream(DownloadFile downloadFile) {
String group = downloadFile.getFileUrl().substring(0, downloadFile.getFileUrl().indexOf("/"));
group = "group1";
String path = downloadFile.getFileUrl().substring(downloadFile.getFileUrl().indexOf("/") + 1);
DownloadByteArray downloadByteArray = new DownloadByteArray();
byte[] bytes = fastFileStorageClient.downloadFile(group, path, downloadByteArray);
InputStream inputStream = new ByteArrayInputStream(bytes);
return inputStream;
}
}

View File

@ -1,62 +0,0 @@
package com.qiwenshare.common.operation.download.product;
import com.qiwenshare.common.operation.download.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();
}
}
}
}
}
@Override
public InputStream getInputStream(DownloadFile downloadFile) {
//设置文件路径
File file = FileOperation.newFile(PathUtil.getStaticPath() + downloadFile.getFileUrl());
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return inputStream;
}
}

View File

@ -1,102 +0,0 @@
package com.qiwenshare.common.operation.upload;
import com.qiwenshare.common.operation.upload.domain.UploadFile;
import com.qiwenshare.common.util.PathUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Slf4j
public abstract class Uploader {
public static final String ROOT_PATH = "upload";
public static final String FILE_SEPARATOR = "/";
// 文件大小限制单位KB
public final int maxSize = 10000000;
public abstract List<UploadFile> upload(HttpServletRequest request, UploadFile uploadFile);
/**
* 获取本地文件保存路径
*
* @return
*/
protected String getLocalFileSavePath() {
String path = ROOT_PATH;
SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
path = FILE_SEPARATOR + path + FILE_SEPARATOR + formater.format(new Date());
String staticPath = PathUtil.getStaticPath();
File dir = new File(staticPath + path);
//LOG.error(PathUtil.getStaticPath() + path);
if (!dir.exists()) {
try {
boolean isSuccessMakeDir = dir.mkdirs();
if (!isSuccessMakeDir) {
log.error("目录创建失败:" + PathUtil.getStaticPath() + path);
}
} catch (Exception e) {
log.error("目录创建失败" + PathUtil.getStaticPath() + path);
return "";
}
}
return path;
}
/**
* 依据原始文件名生成新文件名
*
* @return
*/
protected String getTimeStampName() {
try {
SecureRandom number = SecureRandom.getInstance("SHA1PRNG");
return "" + number.nextInt(10000)
+ System.currentTimeMillis();
} catch (NoSuchAlgorithmException e) {
log.error("生成安全随机数失败");
}
return ""
+ System.currentTimeMillis();
}
public synchronized boolean checkUploadStatus(UploadFile param, File confFile) throws IOException {
RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw");
//设置文件长度
confAccessFile.setLength(param.getTotalChunks());
//设置起始偏移量
confAccessFile.seek(param.getChunkNumber() - 1);
//将指定的一个字节写入文件中 127
confAccessFile.write(Byte.MAX_VALUE);
byte[] completeStatusList = FileUtils.readFileToByteArray(confFile);
confAccessFile.close();//不关闭会造成无法占用
//创建conf文件文件长度为总分片数每上传一个分块即向conf文件中写入一个127那么没上传的位置就是默认的0,已上传的就是127
for (int i = 0; i < completeStatusList.length; i++) {
if (completeStatusList[i] != Byte.MAX_VALUE) {
return false;
}
}
confFile.delete();
return true;
}
protected String getFileName(String fileName){
if (!fileName.contains(".")) {
return fileName;
}
return fileName.substring(0, fileName.lastIndexOf("."));
}
}

View File

@ -1,27 +0,0 @@
package com.qiwenshare.common.operation.upload.domain;
import lombok.Data;
@Data
public class UploadFile {
private String fileName;
private String fileType;
private long fileSize;
private String timeStampName;
private int success;
private String message;
private String url;
@Deprecated
private Integer isOSS;
private Integer storageType;
//切片上传相关参数
private String taskId;
private int chunkNumber;
private long chunkSize;
private int totalChunks;
private String identifier;
private long totalSize;
private long currentChunkSize;
}

View File

@ -1,224 +0,0 @@
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.config.QiwenFileConfig;
import com.qiwenshare.common.operation.upload.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.Data;
import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.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.*;
@Slf4j
@Component
public class AliyunOSSUploader extends Uploader {
@Resource
QiwenFileConfig qiwenFileConfig;
// partETags是PartETag的集合PartETag由分片的ETag和分片号组成
public static Map<String, List<PartETag>> partETagsMap = new HashMap<String, List<PartETag>>();
public static Map<String, UploadFileInfo> uploadPartRequestMap = new HashMap<>();
public static Map<String, OSS> ossMap = new HashMap<>();
@Override
public List<UploadFile> upload(HttpServletRequest httpServletRequest, UploadFile uploadFile) {
log.info("开始上传upload");
List<UploadFile> saveUploadFileList = new ArrayList<>();
StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest) httpServletRequest;
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
throw new UploadGeneralException("未包含文件上传域");
}
Iterator<String> iter = request.getFileNames();
while (iter.hasNext()) {
saveUploadFileList = doUpload(request, iter, uploadFile);
}
log.info("结束上传");
return saveUploadFileList;
}
private List<UploadFile> doUpload(StandardMultipartHttpServletRequest standardMultipartHttpServletRequest, Iterator<String> iter, UploadFile uploadFile) {
String savePath = getLocalFileSavePath();
OSS ossClient = getClient(uploadFile);
List<UploadFile> saveUploadFileList = new ArrayList<>();
try {
MultipartFile multipartfile = standardMultipartHttpServletRequest.getFile(iter.next());
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 ossFilePath = savePath + FILE_SEPARATOR + timeStampName + FILE_SEPARATOR + fileName + "." + fileType;
String confFilePath = savePath + FILE_SEPARATOR + uploadFile.getIdentifier() + "." + "conf";
File confFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + confFilePath);
synchronized (AliyunOSSUploader.class) {
if (uploadPartRequestMap.get(uploadFile.getIdentifier()) == null) {
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(qiwenFileConfig.getAliyun().getOss().getBucketName());
uploadPartRequest.setKey(ossFilePath.substring(1));
uploadPartRequest.setUploadId(uploadId);
uploadPartRequestMap.put(uploadFile.getIdentifier(), uploadPartRequest);
}
}
UploadFileInfo uploadFileInfo = uploadPartRequestMap.get(uploadFile.getIdentifier());
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(uploadFileInfo.getBucketName());
uploadPartRequest.setKey(uploadFileInfo.getKey());
uploadPartRequest.setUploadId(uploadFileInfo.getUploadId());
uploadPartRequest.setInputStream(multipartfile.getInputStream());
uploadPartRequest.setPartSize(uploadFile.getCurrentChunkSize());
uploadPartRequest.setPartNumber(uploadFile.getChunkNumber());
log.info(JSON.toJSONString(uploadPartRequest));
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
synchronized (AliyunOSSUploader.class) {
log.info("上传结果:" + JSON.toJSONString(uploadPartResult));
if (partETagsMap.get(uploadFile.getIdentifier()) == null) {
List<PartETag> partETags = new ArrayList<PartETag>();
partETags.add(uploadPartResult.getPartETag());
partETagsMap.put(uploadFile.getIdentifier(), partETags);
} else {
partETagsMap.get(uploadFile.getIdentifier()).add(uploadPartResult.getPartETag());
}
}
boolean isComplete = checkUploadStatus(uploadFile, confFile);
if (isComplete) {
log.info("分片上传完成");
completeMultipartUpload(uploadFile);
uploadFile.setUrl("/" + uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey());
uploadFile.setSuccess(1);
uploadFile.setMessage("上传成功");
partETagsMap.remove(uploadFile.getIdentifier());
uploadPartRequestMap.remove(uploadFile.getIdentifier());
ossMap.remove(uploadFile.getIdentifier());
} else {
uploadFile.setSuccess(0);
uploadFile.setMessage("未完成");
}
} catch (Exception e) {
log.error("上传出错:" + e);
throw new UploadGeneralException(e);
}
uploadFile.setIsOSS(1);
uploadFile.setStorageType(1);
uploadFile.setFileSize(uploadFile.getTotalSize());
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
}
/**
* 将文件分块进行升序排序并执行文件上传
*/
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(qiwenFileConfig.getAliyun().getOss().getBucketName(),
uploadFileInfo.getKey(),
uploadFileInfo.getUploadId(),
partETags);
log.info("----:" + JSON.toJSONString(partETags));
// 完成上传
CompleteMultipartUploadResult completeMultipartUploadResult = getClient(uploadFile).completeMultipartUpload(completeMultipartUploadRequest);
log.info("----:" + JSON.toJSONString(completeMultipartUploadRequest));
getClient(uploadFile).shutdown();
//
}
private void listFile(UploadFile uploadFile) {
// 列举已上传的分片其中uploadId来自于InitiateMultipartUpload返回的结果
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(uploadFile).listParts(listPartsRequest);
for (PartSummary part : partListing.getParts()) {
log.info("分片号:"+part.getPartNumber() + ", 分片数据大小: "+
part.getSize() + "分片的ETag:"+part.getETag()
+ " 分片最后修改时间:"+ part.getLastModified());
// 获取分片号
part.getPartNumber();
// 获取分片数据大小
part.getSize();
// 获取分片的ETag
part.getETag();
// 获取分片的最后修改时间
part.getLastModified();
}
}
/**
* 取消上传
*/
private void cancelUpload(UploadFile uploadFile) {
AbortMultipartUploadRequest abortMultipartUploadRequest =
new AbortMultipartUploadRequest(qiwenFileConfig.getAliyun().getOss().getBucketName(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getKey(), uploadPartRequestMap.get(uploadFile.getIdentifier()).getUploadId());
getClient(uploadFile).abortMultipartUpload(abortMultipartUploadRequest);
}
private synchronized OSS getClient(UploadFile uploadFile) {
OSS ossClient = null;
if (ossMap.get(uploadFile.getIdentifier()) == null) {
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());
}
return ossClient;
}
@Data
public class UploadFileInfo {
private String bucketName;
private String key;
private String uploadId;
}
}

View File

@ -1,186 +0,0 @@
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.exception.UploadGeneralException;
import com.qiwenshare.common.operation.upload.Uploader;
import com.qiwenshare.common.operation.upload.domain.UploadFile;
import com.qiwenshare.common.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.common.util.concurrent.locks.RedisLock;
import com.qiwenshare.common.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.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.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class FastDFSUploader extends Uploader {
@Resource
AppendFileStorageClient defaultAppendFileStorageClient;
@Resource
RedisLock redisLock;
@Resource
RedisUtil redisUtil;
@Override
public List<UploadFile> upload(HttpServletRequest request, UploadFile uploadFile) {
List<UploadFile> saveUploadFileList = new ArrayList<>();
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = (StandardMultipartHttpServletRequest) request;
boolean isMultipart = ServletFileUpload.isMultipartContent(standardMultipartHttpServletRequest);
if (!isMultipart) {
throw new UploadGeneralException("未包含文件上传域");
}
String savePath = getLocalFileSavePath();
try {
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());
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("分片上传完成");
String path = redisUtil.getObject(uploadFile.getIdentifier() + "_storage_path");
uploadFile.setUrl(path);
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) {
redisLock.lock(uploadFile.getIdentifier());
try {
if (redisUtil.getObject(uploadFile.getIdentifier() + "_current_upload_chunk_number") == null) {
redisUtil.set(uploadFile.getIdentifier() + "_current_upload_chunk_number", 1, 1000 * 60 * 60);
}
String currentUploadChunkNumber = redisUtil.getObject(uploadFile.getIdentifier() + "_current_upload_chunk_number");
if (uploadFile.getChunkNumber() != Integer.parseInt(currentUploadChunkNumber)) {
redisLock.unlock(uploadFile.getIdentifier());
while (redisLock.tryLock(uploadFile.getIdentifier(), 300, TimeUnit.SECONDS)) {
if (uploadFile.getChunkNumber() == Integer.parseInt(redisUtil.getObject(uploadFile.getIdentifier() + "_current_upload_chunk_number"))) {
break;
} else {
redisLock.unlock(uploadFile.getIdentifier());
}
}
}
log.info("***********开始上传第{}块**********", uploadFile.getChunkNumber());
StorePath storePath = null;
redisUtil.getIncr(uploadFile.getIdentifier() + "_current_upload_chunk_number");
if (uploadFile.getChunkNumber() <= 1) {
log.info("上传第一块");
storePath = defaultAppendFileStorageClient.uploadAppenderFile("group1", multipartFile.getInputStream(),
multipartFile.getSize(), FileUtil.getFileExtendName(multipartFile.getOriginalFilename()));
// 记录第一个分片上传的大小
redisUtil.set(uploadFile.getIdentifier() + "_uploaded_size", uploadFile.getCurrentChunkSize(), 1000 * 60 * 60);
log.info("第一块上传完成");
if (storePath == null) {
redisUtil.set(uploadFile.getIdentifier() + "_current_upload_chunk_number", uploadFile.getChunkNumber(), 1000 * 60 * 60);
log.info("获取远程文件路径出错");
throw new UploadGeneralException("获取远程文件路径出错");
}
redisUtil.set(uploadFile.getIdentifier() + "_storage_path", storePath.getPath(), 1000 * 60 * 60);
log.info("上传文件 result = {}", storePath.getPath());
} else {
log.info("正在上传第{}块:" , uploadFile.getChunkNumber());
String path = redisUtil.getObject(uploadFile.getIdentifier() + "_storage_path");
if (path == null) {
log.error("无法获取已上传服务器文件地址");
throw new UploadGeneralException("无法获取已上传服务器文件地址");
}
String uploadedSizeStr = redisUtil.getObject(uploadFile.getIdentifier() + "_uploaded_size");
Long alreadySize = Long.parseLong(uploadedSizeStr);
// 追加方式实际实用如果中途出错多次,可能会出现重复追加情况,这里改成修改模式,即时多次传来重复文件块,依然可以保证文件拼接正确
defaultAppendFileStorageClient.modifyFile("group1", path, multipartFile.getInputStream(),
multipartFile.getSize(), alreadySize);
// 记录分片上传的大小
redisUtil.set(uploadFile.getIdentifier() + "_uploaded_size", alreadySize + multipartFile.getSize(), 1000 * 60 * 60);
}
log.info("***********第{}块上传成功**********", uploadFile.getChunkNumber());
} catch (Exception e) {
log.error("***********第{}块上传失败,自动重试**********", uploadFile.getChunkNumber());
redisUtil.set(uploadFile.getIdentifier() + "_current_upload_chunk_number", uploadFile.getChunkNumber(), 1000 * 60 * 60);
throw new UploadGeneralException("更新远程文件出错", e);
} finally {
redisLock.unlock(uploadFile.getIdentifier());
}
}
}

View File

@ -1,125 +0,0 @@
package com.qiwenshare.common.operation.upload.product;
import com.qiwenshare.common.exception.NotSameFileExpection;
import com.qiwenshare.common.operation.upload.domain.UploadFile;
import com.qiwenshare.common.exception.UploadGeneralException;
import com.qiwenshare.common.operation.ImageOperation;
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.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
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.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@Component
public class LocalStorageUploader extends Uploader {
@Override
public List<UploadFile> upload(HttpServletRequest httpServletRequest,UploadFile uploadFile) {
List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
StandardMultipartHttpServletRequest standardMultipartHttpServletRequest = (StandardMultipartHttpServletRequest) httpServletRequest;
boolean isMultipart = ServletFileUpload.isMultipartContent(standardMultipartHttpServletRequest);
if (!isMultipart) {
throw new UploadGeneralException("未包含文件上传域");
}
try {
Iterator<String> iter = standardMultipartHttpServletRequest.getFileNames();
while (iter.hasNext()) {
saveUploadFileList = doUpload(standardMultipartHttpServletRequest, iter, uploadFile);
}
} catch (IOException e) {
throw new UploadGeneralException("未包含文件上传域");
} catch (NotSameFileExpection notSameFileExpection) {
notSameFileExpection.printStackTrace();
}
return saveUploadFileList;
}
private List<UploadFile> doUpload(StandardMultipartHttpServletRequest standardMultipartHttpServletRequest, Iterator<String> iter, UploadFile uploadFile) throws IOException, NotSameFileExpection {
String savePath = getLocalFileSavePath();
List<UploadFile> saveUploadFileList = new ArrayList<UploadFile>();
MultipartFile multipartfile = standardMultipartHttpServletRequest.getFile(iter.next());
String timeStampName = uploadFile.getIdentifier();
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 + "." + fileType;
String tempFilePath = savePath + FILE_SEPARATOR + timeStampName + "." + fileType + "_tmp";
String minFilePath = savePath + FILE_SEPARATOR + timeStampName + "_min" + "." + fileType;
String confFilePath = savePath + FILE_SEPARATOR + timeStampName + "." + "conf";
File file = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + saveFilePath);
File tempFile = new File(PathUtil.getStaticPath() + FILE_SEPARATOR + tempFilePath);
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())) {
uploadFile.setTaskId(UUID.randomUUID().toString());
}
//第一步 打开将要写入的文件
RandomAccessFile raf = new RandomAccessFile(tempFile, "rw");
//第二步 打开通道
FileChannel fileChannel = raf.getChannel();
//第三步 计算偏移量
long position = (uploadFile.getChunkNumber() - 1) * uploadFile.getChunkSize();
//第四步 获取分片数据
byte[] fileData = multipartfile.getBytes();
//第五步 写入数据
fileChannel.position(position);
fileChannel.write(ByteBuffer.wrap(fileData));
fileChannel.force(true);
fileChannel.close();
raf.close();
//判断是否完成文件的传输并进行校验与重命名
boolean isComplete = checkUploadStatus(uploadFile, confFile);
if (isComplete) {
FileInputStream fileInputStream = new FileInputStream(tempFile.getPath());
String md5 = DigestUtils.md5Hex(fileInputStream);
fileInputStream.close();
if (StringUtils.isNotBlank(md5) && !md5.equals(uploadFile.getIdentifier())) {
throw new NotSameFileExpection();
}
tempFile.renameTo(file);
if (FileUtil.isImageFile(uploadFile.getFileType())){
ImageOperation.thumbnailsImage(file, minFile, 300);
}
uploadFile.setSuccess(1);
uploadFile.setMessage("上传成功");
} else {
uploadFile.setSuccess(0);
uploadFile.setMessage("未完成");
}
uploadFile.setFileSize(uploadFile.getTotalSize());
saveUploadFileList.add(uploadFile);
return saveUploadFileList;
}
}

View File

@ -1,73 +0,0 @@
package com.qiwenshare.common.result;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 统一结果返回
* @param <T>
*/
@Data
@Schema(name = "统一结果返回",required = true)
public class RestResult<T> {
@Schema(description = "请求是否成功", example = "true")
private Boolean success = true;
@Schema(description = "返回码", example = "20000")
private Integer code;
@Schema(description = "返回信息", example = "成功")
private String message;
@Schema(description = "返回数据")
private T data;
// 通用返回成功
public static RestResult success() {
RestResult r = new RestResult();
r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
r.setCode(ResultCodeEnum.SUCCESS.getCode());
r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
return r;
}
// 通用返回失败未知错误
public static RestResult fail() {
RestResult r = new RestResult();
r.setSuccess(ResultCodeEnum.UNKNOWN_ERROR.getSuccess());
r.setCode(ResultCodeEnum.UNKNOWN_ERROR.getCode());
r.setMessage(ResultCodeEnum.UNKNOWN_ERROR.getMessage());
return r;
}
// 设置结果形参为结果枚举
public static RestResult setResult(ResultCodeEnum result) {
RestResult r = new RestResult();
r.setSuccess(result.getSuccess());
r.setCode(result.getCode());
r.setMessage(result.getMessage());
return r;
}
// 自定义返回数据
public RestResult data(T param) {
this.setData(param);
return this;
}
// 自定义状态信息
public RestResult message(String message) {
this.setMessage(message);
return this;
}
// 自定义状态码
public RestResult code(Integer code) {
this.setCode(code);
return this;
}
// 自定义返回结果
public RestResult success(Boolean success) {
this.setSuccess(success);
return this;
}
}

View File

@ -1,31 +0,0 @@
package com.qiwenshare.common.result;
import lombok.Getter;
/**
* 结果类枚举
*/
@Getter
public enum ResultCodeEnum {
SUCCESS(true,20000,"成功"),
UNKNOWN_ERROR(false,20001,"未知错误"),
PARAM_ERROR(false,20002,"参数错误"),
NULL_POINT(false, 20003, "空指针异常"),
INDEX_OUT_OF_BOUNDS(false, 20004, "下标越界异常"),
REQUEST_TIMEOUT(false, 20005, "请求超时"),
NOT_LOGIN_ERROR(false, 20006, "未登录异常"),
;
// 响应是否成功
private Boolean success;
// 响应状态码
private Integer code;
// 响应信息
private String message;
ResultCodeEnum(boolean success, Integer code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
}

View File

@ -1,61 +0,0 @@
package com.qiwenshare.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 通信工具类
*
* @author ma116
*/
public class CollectUtil {
private static final Logger LOG = LoggerFactory.getLogger(CollectUtil.class);
/**
* java 后台获取访问客户端ip地址
*
* @param request HttpServletRequest请求
* @return IP地址
*/
public String getClientIpAddress(HttpServletRequest request) {
String clientIp = request.getHeader("x-forwarded-for");
if (clientIp == null || clientIp.length() == 0
|| "unknown".equalsIgnoreCase(clientIp)) {
clientIp = request.getHeader("Proxy-Client-IP");
}
if (clientIp == null || clientIp.length() == 0
|| "unknown".equalsIgnoreCase(clientIp)) {
clientIp = request.getHeader("WL-Proxy-Client-IP");
}
if (clientIp == null || clientIp.length() == 0
|| "unknown".equalsIgnoreCase(clientIp)) {
clientIp = request.getRemoteAddr();
}
return clientIp;
}
/**
* 获取本地IP
*
* @return IP地址
*/
public String getLocalIp() {
InetAddress addr = null;
String ip = "";
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
LOG.error("获取本地IP失败");
}
if (addr != null) {
ip = addr.getHostAddress().toString();
}
return ip;
}
}

View File

@ -1,127 +0,0 @@
package com.qiwenshare.common.util;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.util.RandomUtil;
import org.apache.commons.lang3.RandomUtils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class DateUtil {
/**
* 获取系统当前时间
*
* @return 系统当前时间
*/
public static String getCurrentTime() {
Date date = new Date();
String stringDate = String.format("%tF %<tT", date);
return stringDate;
}
/**
* @param stringDate 日期字符串"2000-03-19"
* @param formatString 格式"yyyy-MM-dd"
* @return 日期
* @throws ParseException 解析异常
*/
public static Date getDateByFormatString(String stringDate, String formatString) throws ParseException {
DateFormat dateFormat = new SimpleDateFormat(formatString);
Date date = dateFormat.parse(stringDate);
return date;
}
/**
* 两个日期相差天数
*
* @param preDate 第一个时间日期
* @param afterDate 第二个时间十七
* @return 相差的天数
*/
public static int getDifferentDays(Date preDate, Date afterDate) {
int preYear = getYear(preDate);
int afterYear = getYear(afterDate);
int preDayOfYear = getDayOfYear(preDate);
int afterDayOfYear = getDayOfYear(afterDate);
if (afterYear - preYear == 0) {
return afterDayOfYear - preDayOfYear;
} else {
int diffDay = 0;
while (preYear < afterYear) {
if (diffDay == 0 && isLeapYear(preYear)) {
diffDay = 366 - preDayOfYear;
} else if (diffDay == 0 && !isLeapYear(preYear)) {
diffDay = 365 - preDayOfYear;
} else if (isLeapYear(preYear)) {
diffDay += 366;
} else {
diffDay += 365;
}
preYear++;
}
diffDay += afterDayOfYear;
return diffDay;
}
}
/**
* 一年中的第几天
*
* @param date 日期
* @return 第几天
*/
public static int getDayOfYear(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int day = cal.get(Calendar.DAY_OF_YEAR);
return day;
}
/**
* 获取年份
* jdk推荐写法date.getYear()已被废弃
*
* @param date 日期
* @return 年份
*/
public static int getYear(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
return year;
}
/**
* 判断是否是闰年
*
* @param year 如2010
* @return 是否闰年
*/
public static boolean isLeapYear(int year) {
if ((year % 4 == 0 && year % 100 != 0)
|| year % 400 == 0) {
return true;
}
return false;
}
public static long getTime() {
long time = new Date().getTime();
return time;
}
public static void main(String[] args) {
System.out.println(RandomUtil.randomInt(6));
}
}

View File

@ -1,95 +0,0 @@
package com.qiwenshare.common.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FileUtil {
public static final String[] IMG_FILE = {"bmp", "jpg", "png", "tif", "gif", "jpeg"};
public static final String[] DOC_FILE = {"doc", "docx", "ppt", "pptx", "xls", "xlsx", "txt", "hlp", "wps", "rtf", "html", "pdf"};
public static final String[] VIDEO_FILE = {"avi", "mp4", "mpg", "mov", "swf"};
public static final String[] MUSIC_FILE = {"wav", "aif", "au", "mp3", "ram", "wma", "mmf", "amr", "aac", "flac"};
public static final int IMAGE_TYPE = 1;
public static final int DOC_TYPE = 2;
public static final int VIDEO_TYPE = 3;
public static final int MUSIC_TYPE = 4;
public static final int OTHER_TYPE = 5;
public static final int SHARE_FILE = 6;
public static final int RECYCLE_FILE = 7;
public static List<String> getFileExtendsByType(int fileType) {
List<String> fileExtends;
switch (fileType) {
case IMAGE_TYPE:
fileExtends = Arrays.asList(IMG_FILE);
break;
case DOC_TYPE:
fileExtends = Arrays.asList(DOC_FILE);
break;
case VIDEO_TYPE:
fileExtends = Arrays.asList(VIDEO_FILE);
break;
case MUSIC_TYPE:
fileExtends = Arrays.asList(MUSIC_FILE);
break;
default:
fileExtends = new ArrayList<>();
break;
}
return fileExtends;
}
/**
* 判断是否为图片文件
*
* @param extendName 文件扩展名
* @return 是否为图片文件
*/
public static boolean isImageFile(String extendName) {
for (int i = 0; i < IMG_FILE.length; i++) {
if (extendName.equalsIgnoreCase(IMG_FILE[i])) {
return true;
}
}
return false;
}
public static String pathSplitFormat(String filePath) {
String path = filePath.replace("///", "/")
.replace("//", "/")
.replace("\\\\\\", "\\")
.replace("\\\\", "\\");
return path;
}
/**
* 获取文件扩展名
* @param fileName 文件名
* @return 文件扩展名
*/
public static String getFileExtendName(String fileName) {
if (fileName.lastIndexOf(".") == -1) {
return "";
}
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
/**
* 获取不包含扩展名的文件名
*
* @param fileName 文件名
* @return 文件名不带扩展名
*/
public static String getFileNameNotExtend(String fileName) {
String fileType = getFileExtendName(fileName);
return fileName.replace("." + fileType, "");
}
}

View File

@ -1,92 +0,0 @@
package com.qiwenshare.common.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;
//import org.apache.commons.net.util.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class JjwtUtil {
// jtijwt的唯一身份标识
public static final String JWT_ID = UUID.randomUUID().toString();
// 加密密文私钥
public static final String JWT_SECRET = "jiamimiwen";
// 过期时间单位毫秒
public static final int EXPIRE_TIME = 60 * 60 * 1000 * 24 * 7; // 一个星期
// 由字符串生成加密key
public static SecretKey generalKey() {
String secret = JWT_SECRET;
// 本地的密码解码
byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);
// 根据给定的字节数组使用AES加密算法构造一个密钥
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
// 创建jwt
public static String createJWT(String issuer, String audience, String subject) throws Exception {
// 设置头部信息
// Map<String, Object> header = new HashMap<String, Object>();
// header.put("typ", "JWT");
// header.put("alg", "HS256");
//
// 指定header那部分签名的时候使用的签名算法jjwt已经将这部分内容封装好了只有{"alg":"HS256"}
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 创建payload的私有声明根据特定的业务需要添加如果要拿这个做验证一般是需要和jwt的接收方提前沟通好验证的方式
Map<String, Object> claims = new HashMap<>(2);
claims.put("username", "admin");
claims.put("password", "010203");
// jti用户id例如20da39f8-b74e-4a9b-9a0f-a39f1f73fe64
String jwtId = JWT_ID;
// 生成JWT的时间
long nowTime = System.currentTimeMillis();
Date issuedAt = new Date(nowTime);
// 生成签名的时候使用的秘钥secret切记这个秘钥不能外露是你服务端的私钥在任何场景都不应该流露出去一旦客户端得知这个secret那就意味着客户端是可以自我签发jwt的
SecretKey key = generalKey();
// 为payload添加各种标准声明和私有声明
JwtBuilder builder = Jwts.builder() // 表示new一个JwtBuilder设置jwt的body
// .setHeader(header) // 设置头部信息
.setClaims(claims) // 如果有私有声明一定要先设置自己创建的这个私有声明这是给builder的claim赋值一旦写在标准的声明赋值之后就是覆盖了那些标准的声明
.setId(jwtId) // jti(JWT ID)jwt的唯一身份标识根据业务需要可以设置为一个不重复的值主要用来作为一次性token从而回避重放攻击
.setIssuedAt(issuedAt) // iat(issuedAt)jwt的签发时间
.setIssuer(issuer) // iss(issuer)jwt签发者
.setSubject(subject) // sub(subject)jwt所面向的用户放登录的用户名一个json格式的字符串可存放useridroldid之类作为用户的唯一标志
.signWith(signatureAlgorithm, key); // 设置签名使用的是签名算法和签名使用的秘钥
// 设置过期时间
long expTime = EXPIRE_TIME;
if (expTime >= 0) {
long exp = nowTime + expTime;
builder.setExpiration(new Date(exp));
}
// 设置jwt接收者
if (audience == null || "".equals(audience)) {
builder.setAudience("Tom");
} else {
builder.setAudience(audience);
}
return builder.compact();
}
// 解密jwt
public static Claims parseJWT(String jwt) throws Exception {
SecretKey key = generalKey(); // 签名秘钥和生成的签名的秘钥一模一样
Claims claims = Jwts.parser() // 得到DefaultJwtParser
.setSigningKey(key) // 设置签名的秘钥
.parseClaimsJws(jwt).getBody(); // 设置需要解析的jwt
return claims;
}
}

View File

@ -1,202 +0,0 @@
package com.qiwenshare.common.util;
import java.util.HashMap;
import java.util.Map;
public class MimeUtils {
public static String getMime(String suffix){
return map.get(suffix);
}
private static Map<String,String> map=new HashMap<String,String>();
static{
map.put("323","text/h323");
map.put("acx","application/internet-property-stream");
map.put("ai","application/postscript");
map.put("aif","audio/x-aiff");
map.put("aifc","audio/x-aiff");
map.put("aiff","audio/x-aiff");
map.put("asf","video/x-ms-asf");
map.put("asr","video/x-ms-asf");
map.put("asx","video/x-ms-asf");
map.put("au","audio/basic");
map.put("avi","video/x-msvideo");
map.put("axs","application/olescript");
map.put("bas","text/plain");
map.put("bcpio","application/x-bcpio");
map.put("bin","application/octet-stream");
map.put("bmp","image/bmp");
map.put("c","text/plain");
map.put("cat","application/vnd.ms-pkiseccat");
map.put("cdf","application/x-cdf");
map.put("cer","application/x-x509-ca-cert");
map.put("class","application/octet-stream");
map.put("clp","application/x-msclip");
map.put("cmx","image/x-cmx");
map.put("cod","image/cis-cod");
map.put("cpio","application/x-cpio");
map.put("crd","application/x-mscardfile");
map.put("crl","application/pkix-crl");
map.put("crt","application/x-x509-ca-cert");
map.put("csh","application/x-csh");
map.put("css","text/css");
map.put("dcr","application/x-director");
map.put("der","application/x-x509-ca-cert");
map.put("dir","application/x-director");
map.put("dll","application/x-msdownload");
map.put("dms","application/octet-stream");
map.put("doc","application/msword");
map.put("dot","application/msword");
map.put("dvi","application/x-dvi");
map.put("dxr","application/x-director");
map.put("eps","application/postscript");
map.put("etx","text/x-setext");
map.put("evy","application/envoy");
map.put("exe","application/octet-stream");
map.put("fif","application/fractals");
map.put("flr","x-world/x-vrml");
map.put("gif","image/gif");
map.put("gtar","application/x-gtar");
map.put("gz","application/x-gzip");
map.put("h","text/plain");
map.put("hdf","application/x-hdf");
map.put("hlp","application/winhlp");
map.put("hqx","application/mac-binhex40");
map.put("hta","application/hta");
map.put("htc","text/x-component");
map.put("htm","text/plain");
map.put("html","text/plain");
map.put("htt","text/webviewhtml");
map.put("ico","image/x-icon");
map.put("ief","image/ief");
map.put("iii","application/x-iphone");
map.put("ins","application/x-internet-signup");
map.put("isp","application/x-internet-signup");
map.put("jfif","image/pipeg");
map.put("jpe","image/jpeg");
map.put("jpeg","image/jpeg");
map.put("jpg","image/jpeg");
map.put("js","application/x-javascript");
map.put("latex","application/x-latex");
map.put("lha","application/octet-stream");
map.put("lsf","video/x-la-asf");
map.put("lsx","video/x-la-asf");
map.put("lzh","application/octet-stream");
map.put("m13","application/x-msmediaview");
map.put("m14","application/x-msmediaview");
map.put("m3u","audio/x-mpegurl");
map.put("man","application/x-troff-man");
map.put("mdb","application/x-msaccess");
map.put("me","application/x-troff-me");
map.put("mht","message/rfc822");
map.put("mhtml","message/rfc822");
map.put("mid","audio/mid");
map.put("mny","application/x-msmoney");
map.put("mov","video/quicktime");
map.put("movie","video/x-sgi-movie");
map.put("mp2","video/mpeg");
map.put("mp3","audio/mpeg");
map.put("mp4","video/mp4");
map.put("mpa","video/mpeg");
map.put("mpe","video/mpeg");
map.put("mpeg","video/mpeg");
map.put("mpg","video/mpeg");
map.put("mpp","application/vnd.ms-project");
map.put("mpv2","video/mpeg");
map.put("ms","application/x-troff-ms");
map.put("mvb","application/x-msmediaview");
map.put("nws","message/rfc822");
map.put("oda","application/oda");
map.put("p10","application/pkcs10");
map.put("p12","application/x-pkcs12");
map.put("p7b","application/x-pkcs7-certificates");
map.put("p7c","application/x-pkcs7-mime");
map.put("p7m","application/x-pkcs7-mime");
map.put("p7r","application/x-pkcs7-certreqresp");
map.put("p7s","application/x-pkcs7-signature");
map.put("pbm","image/x-portable-bitmap");
map.put("pdf","application/pdf");
map.put("pfx","application/x-pkcs12");
map.put("pgm","image/x-portable-graymap");
map.put("pko","application/ynd.ms-pkipko");
map.put("pma","application/x-perfmon");
map.put("pmc","application/x-perfmon");
map.put("pml","application/x-perfmon");
map.put("pmr","application/x-perfmon");
map.put("pmw","application/x-perfmon");
map.put("pnm","image/x-portable-anymap");
map.put("pot,","application/vnd.ms-powerpoint");
map.put("ppm","image/x-portable-pixmap");
map.put("pps","application/vnd.ms-powerpoint");
map.put("ppt","application/vnd.ms-powerpoint");
map.put("prf","application/pics-rules");
map.put("ps","application/postscript");
map.put("pub","application/x-mspublisher");
map.put("qt","video/quicktime");
map.put("ra","audio/x-pn-realaudio");
map.put("ram","audio/x-pn-realaudio");
map.put("ras","image/x-cmu-raster");
map.put("rgb","image/x-rgb");
map.put("rmi","audio/mid");
map.put("roff","application/x-troff");
map.put("rtf","application/rtf");
map.put("rtx","text/richtext");
map.put("scd","application/x-msschedule");
map.put("sct","text/scriptlet");
map.put("setpay","application/set-payment-initiation");
map.put("setreg","application/set-registration-initiation");
map.put("sh","application/x-sh");
map.put("shar","application/x-shar");
map.put("sit","application/x-stuffit");
map.put("snd","audio/basic");
map.put("spc","application/x-pkcs7-certificates");
map.put("spl","application/futuresplash");
map.put("src","application/x-wais-source");
map.put("sst","application/vnd.ms-pkicertstore");
map.put("stl","application/vnd.ms-pkistl");
map.put("stm","text/html");
map.put("svg","image/svg+xml");
map.put("sv4cpio","application/x-sv4cpio");
map.put("sv4crc","application/x-sv4crc");
map.put("swf","application/x-shockwave-flash");
map.put("t","application/x-troff");
map.put("tar","application/x-tar");
map.put("tcl","application/x-tcl");
map.put("tex","application/x-tex");
map.put("texi","application/x-texinfo");
map.put("texinfo","application/x-texinfo");
map.put("tgz","application/x-compressed");
map.put("tif","image/tiff");
map.put("tiff","image/tiff");
map.put("tr","application/x-troff");
map.put("trm","application/x-msterminal");
map.put("tsv","text/tab-separated-values");
map.put("txt","text/plain");
map.put("uls","text/iuls");
map.put("ustar","application/x-ustar");
map.put("vcf","text/x-vcard");
map.put("vrml","x-world/x-vrml");
map.put("wav","audio/x-wav");
map.put("wcm","application/vnd.ms-works");
map.put("wdb","application/vnd.ms-works");
map.put("wks","application/vnd.ms-works");
map.put("wmf","application/x-msmetafile");
map.put("wps","application/vnd.ms-works");
map.put("wri","application/x-mswrite");
map.put("wrl","x-world/x-vrml");
map.put("wrz","x-world/x-vrml");
map.put("xaf","x-world/x-vrml");
map.put("xbm","image/x-xbitmap");
map.put("xla","application/vnd.ms-excel");
map.put("xlc","application/vnd.ms-excel");
map.put("xlm","application/vnd.ms-excel");
map.put("xls","application/vnd.ms-excel");
map.put("xlt","application/vnd.ms-excel");
map.put("xlw","application/vnd.ms-excel");
map.put("xof","x-world/x-vrml");
map.put("xpm","image/x-xpixmap");
map.put("xwd","image/x-xwindowdump");
map.put("z","application/x-compress");
map.put("zip","application/zip");
}
}

View File

@ -1,19 +0,0 @@
package com.qiwenshare.common.util;
import java.util.Random;
public class PasswordUtil {
public static String getSaltValue() {
Random r = new Random();
StringBuilder sb = new StringBuilder(16);
sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
int len = sb.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sb.append("0");
}
}
String salt = sb.toString();
return salt;
}
}

View File

@ -1,80 +0,0 @@
package com.qiwenshare.common.util;
import cn.hutool.core.util.RandomUtil;
import com.qiwenshare.common.constant.FileConstant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
public class PathUtil {
/**
* 获取项目所在的根目录路径 resources路径
* @return
*/
public static String getProjectRootPath() {
String absolutePath = null;
try {
String url = ResourceUtils.getURL("classpath:").getPath();
absolutePath = urlDecode(new File(url).getAbsolutePath()) + File.separator;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return absolutePath;
}
/**
* 路径解码
* @param url
* @return
*/
public static String urlDecode(String url){
String decodeUrl = null;
try {
decodeUrl = URLDecoder.decode(url, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return decodeUrl;
}
/**
* 得到static路径
*
* @return
*/
public static String getStaticPath() {
String localStoragePath = PropertiesUtil.getProperty("qiwen-file.local-storage-path");
if (StringUtils.isNotEmpty(localStoragePath)) {
return localStoragePath;
}else {
String projectRootAbsolutePath = getProjectRootPath();
int index = projectRootAbsolutePath.indexOf("file:");
if (index != -1) {
projectRootAbsolutePath = projectRootAbsolutePath.substring(0, index);
}
return projectRootAbsolutePath + "static" + File.separator;
}
}
public static String getParentPath(String path) {
return path.substring(0, path.lastIndexOf(FileConstant.pathSeparator));
}
public static void main(String[] args) {
System.out.println(RandomUtil.randomLong(999999));
// String path = "aaa/bbb/ccc/";
// System.out.println(getParentPath(path));
// String fileName = path.substring(path.lastIndexOf("/"));
// System.out.println(fileName);
}
}

View File

@ -1,18 +0,0 @@
package com.qiwenshare.common.util;
import org.springframework.core.env.Environment;
public class PropertiesUtil {
private static Environment env = null;
public static void setEnvironment(Environment env) {
PropertiesUtil.env = env;
}
public static String getProperty(String key) {
return PropertiesUtil.env.getProperty(key);
}
}

View File

@ -1,98 +0,0 @@
package com.qiwenshare.common.util;
import io.netty.util.internal.StringUtil;
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.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@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);
}
/**
* @Description: 获取自增长值
* @param key key
* @return
*/
public Long getIncr(String key) {
Long count = redisTemplate.opsForValue().increment(key, 1);
return count;
}
// public static void main(String[] args) {
// Lock
// }
}

View File

@ -1,240 +0,0 @@
package com.qiwenshare.common.util.concurrent.locks;
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 org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
/**
* redis实现分布式锁
*
*/
@Component
public class RedisLock{
private static final Logger log = LoggerFactory.getLogger(RedisLock.class);
/**
* 默认轮休获取锁间隔时间 单位毫秒
*/
private static final int DEFAULT_ACQUIRE_RESOLUTION_MILLIS = 100;
private static final String UNLOCK_LUA;
private static final long LOCK_EXPIRE_TIME = 60 * 15; //获取锁最大15分钟就会过期
@Resource
RedisTemplate<String, Object> redisTemplate;
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 final ThreadLocal<Map<String, LockVO>> lockMap = new ThreadLocal<>();
/**
* 获取锁没有获取到则一直等待
*
* @param key redis key
*/
public void lock(final String key) {
try {
acquireLock(key, LOCK_EXPIRE_TIME, -1);
} 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);
}
}
public boolean tryLock(final String key) {
try {
return acquireLock(key, LOCK_EXPIRE_TIME, -1);
} catch (Exception e) {
throw new RuntimeException("acquire lock exception", e);
}
}
/**
* 获取锁指定时间内没有获取到返回false否则 返回true
*
* @param key redis key
* @param waitTime 获取锁超时时间, -1代表永不超时, 单位
*/
public boolean tryLock(String key, long time, TimeUnit unit) {
try {
return acquireLock(key, LOCK_EXPIRE_TIME, unit.toSeconds(time));
} catch (Exception e) {
throw new RuntimeException("acquire 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;
}
/**
* 释放锁
*
* @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) {
try{
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);
} catch (Exception e) {
log.error("redis lock error.", e);
}
return false;
}
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;
}
}
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;
}
}

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This is the JRebel configuration file. It maps the running application to your IDE workspace, enabling JRebel reloading for this project.
Refer to https://manuals.jrebel.com/jrebel/standalone/config.html for more information.
-->
<application generated-by="intellij" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_3.xsd">
<id>file-common</id>
<classpath>
<dir name="E:/workspace/qiwen-file/file-common/target/classes">
</dir>
</classpath>
</application>

29
file-web/.gitignore vendored
View File

@ -1,29 +0,0 @@
HELP.md
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
/build/
### VS Code ###
.vscode/

View File

@ -1,171 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.qiwenshare</groupId>
<artifactId>file</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.qiwenshare</groupId>
<artifactId>file-web</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>file-web</name>
<description>fileos.qiwenshare.com</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
<skipTests>true</skipTests>
<docker.image.prefix>scp</docker.image.prefix>
<release-path>target/../../release</release-path>
<app-name>${project.artifactId}-${project.version}</app-name>
</properties>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--mybatis end-->
<!-- spring boot依赖包 -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-web</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.mybatis.spring.boot</groupId>-->
<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!-- </dependency>-->
<!--登陆认证和权限管理-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.qiwenshare</groupId>
<artifactId>file-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!--排除静态文件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<!-- 添加index则不从mainfest中读取classpath而是从Index.list中读取 -->
<!-- <index>true</index> -->
<manifest>
<mainClass>com.qiwenshare.file.FileApplication</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>static/**</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- not append assembly id in release file name -->
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>../file-common/src/main/resources/conf/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!--ant插件执行自定义动作-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy todir="${release-path}" >
<fileset dir="target/${app-name}/${app-name}">
</fileset>
</copy>
<!-- <copy file="target/classes/script/startup.bat" tofile="${release-path}/startup.bat"/>-->
<!-- <copy file="target/classes/script/startup.sh" tofile="${release-path}/startup.sh"/>-->
<!-- <copy file="target/classes/script/stop.sh" tofile="${release-path}/stop.sh"/>-->
<!-- <copy todir="${release-path}">-->
<!-- <fileset dir="target/classes">-->
<!-- <include name="**/static/**" />-->
<!-- </fileset>-->
<!-- </copy>-->
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,4 +1,4 @@
set settingDir=file-common/src/main/resources/conf/settings.xml
set settingDir=src/main/resources/build/settings.xml
mvn clean install -s %settingDir%
pause

183
pom.xml
View File

@ -1,25 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<groupId>com.qiwenshare</groupId>
<artifactId>qiwenshare</artifactId>
<version>1.0.1</version>
</parent>
<groupId>com.qiwenshare</groupId>
<artifactId>file</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<artifactId>qiwen-file</artifactId>
<version>1.0.1-SNAPSHOT</version>
<name>qiwen-file</name>
<description>fileos.qiwenshare.com</description>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
<!-- <spring-cloud.version>Hoxton.SR9</spring-cloud.version>-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
<skipTests>true</skipTests>
<docker.image.prefix>scp</docker.image.prefix>
<release-path>target/../release</release-path>
<app-name>${project.artifactId}-${project.version}</app-name>
</properties>
<dependencies>
@ -31,11 +33,7 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springdoc</groupId>-->
<!-- <artifactId>springdoc-openapi-ui</artifactId>-->
<!-- <version>1.5.4</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
@ -52,7 +50,6 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- 导入Mysql数据库链接jar包-->
@ -73,38 +70,134 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--mybatis end-->
<!--登陆认证和权限管理-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.qiwenshare</groupId>
<artifactId>ufo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-dependencies</artifactId>-->
<!-- <version>${spring-cloud.version}</version>-->
<!-- <type>pom</type>-->
<!-- <scope>import</scope>-->
<!-- </dependency>-->
<build>
<plugins>
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!--排除静态文件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<!-- 添加index则不从mainfest中读取classpath而是从Index.list中读取 -->
<!-- <index>true</index> -->
<manifest>
<mainClass>com.qiwenshare.file.FileApplication</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<excludes>
<exclude>static/**</exclude>
</excludes>
</configuration>
</plugin>
</dependencies>
</dependencyManagement>
<modules>
<module>file-common</module>
<module>file-web</module>
</modules>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<!-- not append assembly id in release file name -->
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/resources/build/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</project>
<!--ant插件执行自定义动作-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy todir="${release-path}" >
<fileset dir="target/${app-name}/${app-name}">
</fileset>
</copy>
<!-- <copy file="target/classes/script/startup.bat" tofile="${release-path}/startup.bat"/>-->
<!-- <copy file="target/classes/script/startup.sh" tofile="${release-path}/startup.sh"/>-->
<!-- <copy file="target/classes/script/stop.sh" tofile="${release-path}/stop.sh"/>-->
<!-- <copy todir="${release-path}">-->
<!-- <fileset dir="target/classes">-->
<!-- <include name="**/static/**" />-->
<!-- </fileset>-->
<!-- </copy>-->
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -16,13 +16,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@MapperScan("com.qiwenshare.file.mapper")
@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

@ -3,7 +3,8 @@ package com.qiwenshare.file.advice;
import com.qiwenshare.common.exception.NotLoginException;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.result.ResultCodeEnum;
import com.qiwenshare.common.exception.UploadGeneralException;
import com.qiwenshare.ufo.exception.UploadException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ -50,10 +51,10 @@ public class GlobalExceptionHandlerAdvice {
return RestResult.setResult(ResultCodeEnum.INDEX_OUT_OF_BOUNDS);
}
@ExceptionHandler(UploadGeneralException.class)
@ExceptionHandler(UploadException.class)
@ResponseBody
@ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
public RestResult error(UploadGeneralException e) {
public RestResult error(UploadException e) {
e.printStackTrace();
log.error("全局异常捕获:" + e);
return RestResult.setResult(ResultCodeEnum.REQUEST_TIMEOUT);

View File

@ -1,17 +1,24 @@
package com.qiwenshare.file.component;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiwenshare.common.constant.FileConstant;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.file.api.IElasticSearchService;
import com.qiwenshare.file.config.es.FileSearch;
import com.qiwenshare.file.domain.TreeNode;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.mapper.UserFileMapper;
import com.qiwenshare.file.vo.file.FileListVo;
import com.qiwenshare.ufo.util.PathUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* 文件逻辑处理组件
@ -20,6 +27,8 @@ import java.util.Queue;
public class FileDealComp {
@Resource
UserFileMapper userFileMapper;
@Autowired
private IElasticSearchService elasticSearchService;
/**
* 获取重复文件名
@ -209,4 +218,23 @@ public class FileDealComp {
return isExistPath;
}
public void uploadESByUserFileId(Long userFileId) {
UserFile userFile = new UserFile();
userFile.setUserFileId(userFileId);
List<FileListVo> userfileResult = userFileMapper.userFileList(userFile, null, null);
if (userfileResult != null && userfileResult.size() > 0) {
FileSearch fileSearch = new FileSearch();
BeanUtil.copyProperties(userfileResult.get(0), fileSearch);
elasticSearchService.save(fileSearch);
}
}
public void deleteESByUserFileId(Long userFileId) {
elasticSearchService.deleteById(userFileId);
}
}

View File

@ -1,4 +1,4 @@
package com.qiwenshare.common.config;
package com.qiwenshare.file.config;
import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;

View File

@ -1,4 +1,4 @@
package com.qiwenshare.common.config;
package com.qiwenshare.file.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
@ -29,8 +29,8 @@ public class RedisConfig extends CachingConfigurerSupport {
}
/**
* 设置 redisTemplate 的序列化设置
* @param redisConnectionFactory
* @return
* @param redisConnectionFactory redis连接工厂
* @return redisTemplate
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

View File

@ -1,28 +1,25 @@
package com.qiwenshare.file.controller;
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.exception.NotLoginException;
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.util.FileUtil;
import com.qiwenshare.common.util.PathUtil;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.*;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.file.component.FileDealComp;
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 com.qiwenshare.ufo.factory.UFOFactory;
import com.qiwenshare.ufo.operation.rename.domain.RenameFile;
import com.qiwenshare.ufo.util.PathUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
@ -57,14 +54,14 @@ public class FileController {
IUserService userService;
@Resource
IUserFileService userFileService;
@Resource
UFOFactory ufoFactory;
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Resource
FileDealComp fileDealComp;
@Resource
QiwenFileConfig qiwenFileConfig;
public static Executor executor = Executors.newFixedThreadPool(20);
public static final String CURRENT_MODULE = "文件接口";
@ -97,6 +94,7 @@ public class FileController {
userFile.setUploadTime(DateUtil.getCurrentTime());
userFileService.save(userFile);
fileDealComp.uploadESByUserFileId(userFile.getUserFileId());
return RestResult.success();
}
@ -170,14 +168,14 @@ public class FileController {
userFile.getFilePath() + userFile.getFileName() + "/", sessionUserBean.getUserId());
} else {
FileBean file = fileService.getById(userFile.getFileId());
if (file.getIsOSS() == 1 || file.getStorageType() == 1) {
if (file.getStorageType() == 1) {
String fileUrl = file.getFileUrl();
String newFileUrl = fileUrl.replace(userFile.getFileName(), renameFileDto.getFileName());
rename(qiwenFileConfig.getAliyun().getOss(),
fileUrl.substring(1),
newFileUrl.substring(1));
RenameFile renameFile = new RenameFile();
renameFile.setSrcName(fileUrl.substring(1));
renameFile.setDestName(newFileUrl.substring(1));
ufoFactory.getRenamer(2).rename(renameFile);
LambdaUpdateWrapper<FileBean> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper
.set(FileBean::getFileUrl, newFileUrl)
@ -199,30 +197,11 @@ public class FileController {
}
}
fileDealComp.uploadESByUserFileId(renameFileDto.getUserFileId());
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"})
@ -231,19 +210,17 @@ public class FileController {
public RestResult getFileList(FileListDTO fileListDto, @RequestHeader("token") String token){
UserFile userFile = new UserFile();
if(qiwenFileConfig.isShareMode()){
userFile.setUserId(2L);
}else {
UserBean sessionUserBean = userService.getUserBeanByToken(token);
if (sessionUserBean == null) {
throw new NotLoginException();
}
if (userFile == null) {
return RestResult.fail();
}
userFile.setUserId(sessionUserBean.getUserId());
UserBean sessionUserBean = userService.getUserBeanByToken(token);
if (sessionUserBean == null) {
throw new NotLoginException();
}
if (userFile == null) {
return RestResult.fail();
}
userFile.setUserId(sessionUserBean.getUserId());
List<FileListVo> fileList = null;
userFile.setFilePath(PathUtil.urlDecode(fileListDto.getFilePath()));
@ -290,6 +267,7 @@ public class FileController {
//userFile.setDeleteBatchNum(uuid);
userFileService.deleteUserFile(userFile.getUserFileId(),sessionUserBean.getUserId());
fileDealComp.deleteESByUserFileId(userFile.getUserFileId());
}
return RestResult.success().message("批量删除文件成功");
@ -310,7 +288,7 @@ public class FileController {
throw new NotLoginException();
}
userFileService.deleteUserFile(deleteFileDto.getUserFileId(), sessionUserBean.getUserId());
fileDealComp.deleteESByUserFileId(deleteFileDto.getUserFileId());
return RestResult.success();
@ -459,13 +437,7 @@ public class FileController {
result.setMessage("未登录");
return result;
}
if (qiwenFileConfig.isShareMode()){
if (sessionUserBean.getUserId() > 2){
result.setSuccess(false);
result.setMessage("没权限,请联系管理员!");
return result;
}
}
result.setSuccess(true);
return result;
}
@ -480,9 +452,7 @@ public class FileController {
throw new NotLoginException();
}
long userId = sessionUserBean.getUserId();
if (qiwenFileConfig.isShareMode()){
userId = 2;
}
List<FileListVo> fileList = new ArrayList<>();
Long beginCount = 0L;
if (pageCount == null || currentPage == null) {

View File

@ -1,6 +1,5 @@
package com.qiwenshare.file.controller;
import com.qiwenshare.common.config.QiwenFileConfig;
import com.qiwenshare.common.exception.NotLoginException;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.DateUtil;
@ -11,6 +10,7 @@ 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.component.FileDealComp;
import com.qiwenshare.file.domain.FileBean;
import com.qiwenshare.file.domain.StorageBean;
import com.qiwenshare.file.domain.UserBean;
@ -19,14 +19,10 @@ import com.qiwenshare.file.dto.DownloadFileDTO;
import com.qiwenshare.file.dto.UploadFileDTO;
import com.qiwenshare.file.dto.file.PreviewDTO;
import com.qiwenshare.file.vo.file.UploadFileVo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -49,14 +45,14 @@ public class FiletransferController {
@Resource
FileController fileController;
@Autowired
QiwenFileConfig qiwenFileConfig;
@Resource
IFileService fileService;
@Resource
IUserService userService;
@Resource
IUserFileService userFileService;
@Resource
FileDealComp fileDealComp;
public static final String CURRENT_MODULE = "文件传输接口";
@Operation(summary = "极速上传", description = "校验文件MD5判断文件是否存在如果存在直接上传成功并返回skipUpload=true如果不存在返回skipUpload=false需要再次调用该接口的POST方法", tags = {"filetransfer"})
@ -95,7 +91,7 @@ public class FiletransferController {
userFileService.save(userFile);
fileService.increaseFilePointCount(file.getFileId());
uploadFileVo.setSkipUpload(true);
fileDealComp.uploadESByUserFileId(userFile.getUserFileId());
} else {
uploadFileVo.setSkipUpload(false);
@ -121,6 +117,7 @@ public class FiletransferController {
}
filetransferService.uploadFile(request, uploadFileDto, sessionUserBean.getUserId());
UploadFileVo uploadFileVo = new UploadFileVo();
return RestResult.success().data(uploadFileVo);
@ -180,7 +177,8 @@ public class FiletransferController {
filetransferService.downloadFile(httpServletResponse, downloadFileDTO);
}catch (Exception e){
//org.apache.catalina.connector.ClientAbortException: java.io.IOException: 你的主机中的软件中止了一个已建立的连接
log.error("该异常忽略不做处理");
e.printStackTrace();
log.error("该异常忽略不做处理:" + e);
}
}
@ -195,11 +193,9 @@ public class FiletransferController {
throw new NotLoginException();
}
StorageBean storageBean = new StorageBean();
if (qiwenFileConfig.isShareMode()){
storageBean.setUserId(2L);
}else{
storageBean.setUserId(sessionUserBean.getUserId());
}
storageBean.setUserId(sessionUserBean.getUserId());
Long storageSize = filetransferService.selectStorageSizeByUserId(sessionUserBean.getUserId());
StorageBean storage = new StorageBean();

View File

@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.exception.NotLoginException;
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;
import com.qiwenshare.file.api.IUserFileService;

View File

@ -3,11 +3,9 @@ package com.qiwenshare.file.controller;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
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.common.config.QiwenFileConfig;
import com.qiwenshare.file.domain.UserBean;
import com.qiwenshare.file.dto.user.RegisterDTO;
import com.qiwenshare.file.vo.user.UserLoginVo;
@ -17,7 +15,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ -34,8 +31,6 @@ public class UserController {
@Resource
IUserService userService;
@Autowired
QiwenFileConfig qiwenFileConfig;
public static Map<String, String> verificationCodeMap = new HashMap<>();
@ -43,7 +38,6 @@ public class UserController {
public static final String CURRENT_MODULE = "用户管理";
@Operation(summary = "用户注册", description = "注册账号", tags = {"user"})
@PostMapping(value = "/register")
@MyLog(operation = "用户注册", module = CURRENT_MODULE)
@ -101,9 +95,6 @@ public class UserController {
UserBean sessionUserBean = userService.getUserBeanByToken(token);
if (sessionUserBean != null) {
AliyunOSS oss = qiwenFileConfig.getAliyun().getOss();
String domain = oss.getDomain();
sessionUserBean.setViewDomain(domain);
return RestResult.success().data(sessionUserBean);
} else {

View File

@ -33,9 +33,9 @@ public class FileBean {
@Column(columnDefinition="bigint(10)")
private Long fileSize;
@Column(columnDefinition="int(1)")
@Deprecated
private Integer isOSS;
// @Column(columnDefinition="int(1)")
// @Deprecated
// private Integer isOSS;
@Column(columnDefinition="int(1)")
private Integer storageType;

View File

@ -7,4 +7,5 @@ import lombok.Data;
@Schema(name = "下载文件DTO",required = true)
public class DownloadFileDTO {
private Long userFileId;
private boolean isMin;
}

Some files were not shown because too many files have changed in this diff Show More