384 lines
17 KiB
Java
384 lines
17 KiB
Java
package com.mesasoft.cn.service.impl;
|
|
|
|
import com.mesasoft.cn.WebSketchApplication;
|
|
import com.mesasoft.cn.config.SettingConfig;
|
|
import com.mesasoft.cn.dao.DownloadedDAO;
|
|
import com.mesasoft.cn.dao.FileDAO;
|
|
import com.mesasoft.cn.entity.Category;
|
|
import com.mesasoft.cn.entity.File;
|
|
import com.mesasoft.cn.entity.User;
|
|
import com.mesasoft.cn.model.AuthRecord;
|
|
import com.mesasoft.cn.model.BaseAuthRecord;
|
|
import com.mesasoft.cn.model.FileBasicRecord;
|
|
import com.mesasoft.cn.model.FileRecord;
|
|
import com.mesasoft.cn.modules.constant.ConfigConsts;
|
|
import com.mesasoft.cn.modules.constant.DefaultValues;
|
|
import com.mesasoft.cn.service.IAuthService;
|
|
import com.mesasoft.cn.service.ICategoryService;
|
|
import com.mesasoft.cn.service.IFileService;
|
|
import com.mesasoft.cn.util.BeanUtils;
|
|
import com.mesasoft.cn.util.ServiceUtils;
|
|
import com.zhazhapan.modules.constant.ValueConsts;
|
|
import com.zhazhapan.util.*;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Isolation;
|
|
import org.springframework.transaction.annotation.Propagation;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.URLDecoder;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
import java.util.regex.Pattern;
|
|
|
|
/**
|
|
* @author pantao
|
|
* @since 2018/1/29
|
|
*/
|
|
@Service
|
|
public class FileServiceImpl implements IFileService {
|
|
|
|
private final static Logger logger = LoggerFactory.getLogger(FileServiceImpl.class);
|
|
|
|
private static final String FILE_SUFFIX = "{fileSuffix}";
|
|
|
|
private static final String RANDOM_ID = "{randomId}";
|
|
|
|
private static final String YEAR = "{year}";
|
|
|
|
private static final String MONTH = "{month}";
|
|
|
|
private static final String DAY = "{day}";
|
|
|
|
private static final String AUTHOR = "{author}";
|
|
|
|
private static final String FILE_NAME = "{fileName}";
|
|
|
|
private static final String CATEGORY_NAME = "{categoryName}";
|
|
|
|
private final FileDAO fileDAO;
|
|
|
|
private final ICategoryService categoryService;
|
|
|
|
private final IAuthService authService;
|
|
|
|
private final DownloadedDAO downloadDAO;
|
|
|
|
@Autowired
|
|
public FileServiceImpl(FileDAO fileDAO, ICategoryService categoryService, IAuthService authService,
|
|
DownloadedDAO downloadDAO) {
|
|
this.fileDAO = fileDAO;
|
|
this.categoryService = categoryService;
|
|
this.authService = authService;
|
|
this.downloadDAO = downloadDAO;
|
|
}
|
|
|
|
@Override
|
|
public boolean updateAuth(long id, String auth) {
|
|
int[] au = BeanUtils.getAuth(auth);
|
|
return fileDAO.updateAuthById(id, au[0], au[1], au[2], au[3], au[4]);
|
|
}
|
|
|
|
@Override
|
|
public BaseAuthRecord getAuth(long id) {
|
|
return fileDAO.getAuth(id);
|
|
}
|
|
|
|
@Override
|
|
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
|
|
Exception.class)
|
|
public boolean deleteFiles(String ids) {
|
|
if (Checker.isNotEmpty(ids)) {
|
|
String[] id = ids.split(ValueConsts.COMMA_SIGN);
|
|
for (String s : id) {
|
|
long fileId = Formatter.stringToLong(s);
|
|
String localUrl = fileDAO.getLocalUrlById(fileId);
|
|
FileExecutor.deleteFile(localUrl);
|
|
removeById(fileId);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
|
|
Exception.class)
|
|
public boolean[] updateUrl(int id, String oldLocalUrl, String localUrl, String visitUrl) {
|
|
boolean[] b = new boolean[]{false, false};
|
|
boolean canUpdateLocalUrl = Checker.isExists(oldLocalUrl) && Checker.isNotEmpty(localUrl) && Checker
|
|
.isNotExists(localUrl) && !localUrlExists(localUrl);
|
|
if (canUpdateLocalUrl) {
|
|
FileExecutor.renameTo(oldLocalUrl, localUrl);
|
|
fileDAO.updateLocalUrlById(id, localUrl);
|
|
b[0] = true;
|
|
}
|
|
if (Checker.isNotEmpty(visitUrl) && !visitUrlExists(visitUrl)) {
|
|
fileDAO.updateVisitUrlById(id, visitUrl);
|
|
b[1] = true;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
|
|
Exception.class)
|
|
public boolean updateFileInfo(long id, User user, String name, String category, String tag, String description) {
|
|
File file = fileDAO.getById(id);
|
|
if (Checker.isNotNull(file) && file.getIsUpdatable() == 1) {
|
|
AuthRecord authRecord = authService.getByFileIdAndUserId(id, user.getId());
|
|
String suffix = FileExecutor.getFileSuffix(name);
|
|
boolean canUpdate = (Checker.isNull(authRecord) ? user.getIsUpdatable() == 1 :
|
|
authRecord.getIsUpdatable() == 1) && Checker.isNotEmpty(name) && Pattern.compile(WebSketchApplication.settings.getStringUseEval(ConfigConsts.FILE_SUFFIX_MATCH_OF_SETTING)).matcher(suffix).matches();
|
|
if (canUpdate) {
|
|
String localUrl = file.getLocalUrl();
|
|
java.io.File newFile = new java.io.File(localUrl);
|
|
String visitUrl = file.getVisitUrl();
|
|
String newLocalUrl = localUrl.substring(0, localUrl.lastIndexOf(ValueConsts.SEPARATOR) + 1) + name;
|
|
String newVisitUrl = visitUrl.substring(0, visitUrl.lastIndexOf(ValueConsts.SPLASH_STRING) + 1) + name;
|
|
file.setName(name);
|
|
file.setSuffix(suffix);
|
|
file.setLocalUrl(newLocalUrl);
|
|
file.setVisitUrl(newVisitUrl);
|
|
file.setCategoryId(categoryService.getIdByName(category));
|
|
file.setTag(tag);
|
|
file.setDescription(description);
|
|
boolean isValid = (localUrl.endsWith(ValueConsts.SEPARATOR + name) || (!Checker.isExists(newLocalUrl)
|
|
&& !localUrlExists(newLocalUrl) && !visitUrlExists(newVisitUrl)));
|
|
if (isValid && fileDAO.updateFileInfo(file)) {
|
|
return newFile.renameTo(new java.io.File(newLocalUrl));
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean removeFile(User user, long fileId) {
|
|
File file = fileDAO.getById(fileId);
|
|
boolean isDeleted = false;
|
|
if (Checker.isNotNull(file) && file.getIsDeletable() == 1) {
|
|
AuthRecord authRecord = authService.getByFileIdAndUserId(fileId, user.getId());
|
|
String localUrl = fileDAO.getLocalUrlById(fileId);
|
|
isDeleted = (Checker.isNull(authRecord) ? user.getIsDeletable() == 1 : authRecord.getIsDeletable() == 1)
|
|
&& removeById(fileId);
|
|
if (isDeleted) {
|
|
FileExecutor.deleteFile(localUrl);
|
|
}
|
|
}
|
|
return isDeleted;
|
|
}
|
|
|
|
@Override
|
|
public List<FileRecord> listUserDownloaded(int userId, int offset, String search) {
|
|
return fileDAO.listUserDownloaded(userId, offset, search);
|
|
}
|
|
|
|
@Override
|
|
public List<FileRecord> listUserUploaded(int userId, int offset, String search) {
|
|
return fileDAO.listUserUploaded(userId, offset, search);
|
|
}
|
|
|
|
@Override
|
|
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
|
|
Exception.class)
|
|
public boolean removeById(long id) {
|
|
downloadDAO.removeByFileId(id);
|
|
authService.removeByFileId(id);
|
|
return fileDAO.removeById(id);
|
|
}
|
|
|
|
@Override
|
|
public boolean removeByVisitUrl(String visitUrl) {
|
|
long fileId = fileDAO.getIdByVisitUrl(visitUrl);
|
|
return removeById(fileId);
|
|
}
|
|
|
|
@Override
|
|
public boolean removeByLocalUrl(String localUrl) {
|
|
long fileId = fileDAO.getIdByLocalUrl(localUrl);
|
|
return removeById(fileId);
|
|
}
|
|
|
|
@Override
|
|
public String getResource(String visitUrl, HttpServletRequest request) {
|
|
logger.info("visit url: " + visitUrl);
|
|
boolean downloadable = WebSketchApplication.settings.getBooleanUseEval(ConfigConsts
|
|
.ANONYMOUS_DOWNLOADABLE_OF_SETTING);
|
|
User user = (User) request.getSession().getAttribute(ValueConsts.USER_STRING);
|
|
File file = fileDAO.getFileByVisitUrl(visitUrl);
|
|
AuthRecord authRecord = null;
|
|
if (Checker.isNotNull(file)) {
|
|
authRecord = authService.getByFileIdAndUserId(file.getId(), Checker.isNull(user) ? 0 : user.getId());
|
|
}
|
|
boolean canDownload = Checker.isNotNull(file) && file.getIsDownloadable() == 1 && (downloadable || (Checker
|
|
.isNull(authRecord) ? (Checker.isNotNull(user) && user.getIsDownloadable() == 1) : authRecord
|
|
.getIsDownloadable() == 1));
|
|
if (canDownload) {
|
|
fileDAO.updateDownloadTimesById(file.getId());
|
|
if (Checker.isNotNull(user)) {
|
|
downloadDAO.insertDownload(user.getId(), file.getId());
|
|
}
|
|
return file.getLocalUrl();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
@Override
|
|
public String getLocalUrlByVisitUrl(String visitUrl) {
|
|
return fileDAO.getLocalUrlByVisitUrl(Checker.checkNull(visitUrl));
|
|
}
|
|
|
|
@Override
|
|
public List<FileRecord> listAll(int userId, int offset, int categoryId, String orderBy, String search) {
|
|
return fileDAO.listAll(userId, offset, categoryId, orderBy, search);
|
|
}
|
|
|
|
@Override
|
|
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
|
|
Exception.class)
|
|
public boolean upload(int categoryId, String tag, String description, String prefix, MultipartFile multipartFile,
|
|
User user) {
|
|
if (user.getIsUploadable() == 1) {
|
|
String name = multipartFile.getOriginalFilename();
|
|
String suffix = FileExecutor.getFileSuffix(name);
|
|
String localUrl = SettingConfig.getUploadStoragePath() + ValueConsts.SEPARATOR + name;
|
|
Category category = categoryService.getById(categoryId);
|
|
long maxSize = Formatter.sizeToLong(WebSketchApplication.settings.getStringUseEval(ConfigConsts
|
|
.FILE_MAX_SIZE_OF_SETTING));
|
|
long size = multipartFile.getSize();
|
|
boolean fileExists = localUrlExists(localUrl);
|
|
//检测标签是否合法
|
|
if (WebSketchApplication.settings.getBooleanUseEval(ConfigConsts.TAG_REQUIRE_OF_SETTING)) {
|
|
String[] tags = Checker.checkNull(tag).split(ValueConsts.SPACE);
|
|
if (tags.length <= WebSketchApplication.settings.getIntegerUseEval(ConfigConsts.TAG_SIZE_OF_SETTING)) {
|
|
int maxLength = WebSketchApplication.settings.getIntegerUseEval(ConfigConsts.TAG_LENGTH_OF_SETTING);
|
|
for (String t : tags) {
|
|
if (t.length() > maxLength) {
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
//是否可以上传
|
|
boolean canUpload = !multipartFile.isEmpty() && size <= maxSize && Pattern.compile(WebSketchApplication
|
|
.settings.getStringUseEval(ConfigConsts.FILE_SUFFIX_MATCH_OF_SETTING)).matcher(suffix).matches()
|
|
&& (Checker.isNotExists(localUrl) || !fileExists || WebSketchApplication.settings.getBooleanUseEval
|
|
(ConfigConsts.FILE_COVER_OF_SETTING));
|
|
logger.info("is empty [" + multipartFile.isEmpty() + "], file size [" + size + "], max file size [" +
|
|
maxSize + "]");
|
|
if (canUpload) {
|
|
String visitUrl = getRegularVisitUrl(Checker.isNotEmpty(prefix) && user.getPermission() > 1 ? prefix
|
|
: WebSketchApplication.settings.getStringUseEval(ConfigConsts.CUSTOM_LINK_RULE_OF_SETTING), user,
|
|
name, suffix, category);
|
|
if (fileExists) {
|
|
removeByLocalUrl(localUrl);
|
|
}
|
|
if (visitUrlExists(visitUrl)) {
|
|
removeByVisitUrl(visitUrl);
|
|
}
|
|
try {
|
|
multipartFile.transferTo(new java.io.File(localUrl));
|
|
logger.info("local url of upload file: " + localUrl);
|
|
File file = new File(name, suffix, localUrl, visitUrl, WebUtils.scriptFilter(description),
|
|
WebUtils.scriptFilter(tag), user.getId(), categoryId);
|
|
int[] auth = SettingConfig.getAuth(ConfigConsts.FILE_DEFAULT_AUTH_OF_SETTING);
|
|
file.setAuth(auth[0], auth[1], auth[2], auth[3], auth[4]);
|
|
boolean isSuccess = fileDAO.insertFile(file);
|
|
if (isSuccess) {
|
|
long fileId = fileDAO.getIdByLocalUrl(localUrl);
|
|
if (fileId > 0) {
|
|
authService.insertDefaultAuth(user.getId(), fileId);
|
|
}
|
|
} else {
|
|
FileExecutor.deleteFile(localUrl);
|
|
}
|
|
return isSuccess;
|
|
} catch (Exception e) {
|
|
FileExecutor.deleteFile(localUrl);
|
|
logger.error("save file error: " + e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private String getRegularVisitUrl(String customUrl, User user, String fileName, String suffix, Category category) {
|
|
Date date = new Date();
|
|
suffix = suffix.startsWith(".") ? "" : "." + suffix;
|
|
if (Checker.isNotEmpty(customUrl)) {
|
|
try {
|
|
customUrl = URLDecoder.decode(customUrl, "utf-8");
|
|
} catch (UnsupportedEncodingException e) {
|
|
logger.error(e.getMessage());
|
|
}
|
|
}
|
|
if (!customUrl.contains(FILE_NAME) && !customUrl.contains(RANDOM_ID)) {
|
|
customUrl += (customUrl.endsWith("/") ? "" : "/") + fileName;
|
|
}
|
|
customUrl = customUrl.replace(YEAR, DateUtils.getYear(date)).replace(MONTH, DateUtils.getMonth(date)).replace
|
|
(DAY, DateUtils.getDay(date)).replace(AUTHOR, user.getUsername()).replace(FILE_NAME, fileName)
|
|
.replace(CATEGORY_NAME, Checker.checkNull(Checker.isNull(category) ? "uncategorized" : category
|
|
.getName())).replace(RANDOM_ID, String.valueOf(RandomUtils.getRandomInteger(ValueConsts
|
|
.NINE_INT))).replace(FILE_SUFFIX, suffix);
|
|
return "/file" + (customUrl.startsWith("/") ? "" : "/") + customUrl;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor =
|
|
Exception.class)
|
|
public boolean shareFiles(String prefix, String files, User user) {
|
|
if (Checker.isNotEmpty(files)) {
|
|
String[] paths = files.split(ValueConsts.COMMA_SIGN);
|
|
for (String path : paths) {
|
|
java.io.File f = new java.io.File(path);
|
|
String name = f.getName();
|
|
String suffix = FileExecutor.getFileSuffix(name);
|
|
String visitUrl = getRegularVisitUrl(prefix, user, name, suffix, null);
|
|
if (f.exists() && f.isFile() && !localUrlExists(path) && !visitUrlExists(visitUrl)) {
|
|
File file = new File(name, suffix, path, visitUrl, ValueConsts.EMPTY_STRING,
|
|
ValueConsts.EMPTY_STRING, user.getId(),
|
|
categoryService.getIdByName(DefaultValues.UNCATEGORIZED));
|
|
file.setAuth(ValueConsts.ONE_INT, ValueConsts.ZERO_INT, ValueConsts.ZERO_INT,
|
|
ValueConsts.ZERO_INT, ValueConsts.ONE_INT);
|
|
fileDAO.insertFile(file);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean localUrlExists(String localUrl) {
|
|
return fileDAO.checkLocalUrl(localUrl) > 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean visitUrlExists(String visitUrl) {
|
|
return fileDAO.checkVisitUrl(visitUrl) > 0;
|
|
}
|
|
|
|
@Override
|
|
public long getFileId(String localUrl) {
|
|
try {
|
|
return fileDAO.getIdByLocalUrl(localUrl);
|
|
} catch (Exception e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
public List<FileBasicRecord> listBasicAll(String user, String file, String category, int offset) {
|
|
return (List<FileBasicRecord>) ServiceUtils.invokeFileFilter(fileDAO, "listBasicBy", user, file, category,
|
|
offset);
|
|
}
|
|
}
|