完善文件存储

This commit is contained in:
yizhaorong
2020-06-07 22:27:19 +08:00
parent 787b7147bc
commit 043cdd95b3
18 changed files with 311 additions and 266 deletions
@@ -5,10 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import org.yzr.model.User;
import org.yzr.service.AppService;
import org.yzr.utils.file.PathManager;
@@ -36,9 +33,9 @@ public class AppController {
try {
Subject currentUser = SecurityUtils.getSubject();
User user = (User) currentUser.getPrincipal();
List<AppViewModel> apps = this.appService.findByUser(user);
List<AppViewModel> apps = this.appService.findByUser(user, request);
request.setAttribute("apps", apps);
request.setAttribute("baseURL", this.pathManager.getBaseURL(false));
request.setAttribute("baseURL", PathManager.request(request).getBaseURL());
} catch (Exception e) {
e.printStackTrace();
}
@@ -49,7 +46,9 @@ public class AppController {
@RequiresPermissions("/apps/get")
@GetMapping("/apps/{appID}")
public String getAppById(@PathVariable("appID") String appID, HttpServletRequest request) {
AppViewModel appViewModel = this.appService.getById(appID);
Subject currentUser = SecurityUtils.getSubject();
User user = (User) currentUser.getPrincipal();
AppViewModel appViewModel = this.appService.getById(appID, user, request);
request.setAttribute("package", appViewModel);
request.setAttribute("apps", appViewModel.getPackageList());
return "list";
@@ -58,8 +57,10 @@ public class AppController {
@RequiresPermissions("/packageList/get")
@RequestMapping("/packageList/{appID}")
@ResponseBody
public Map<String, Object> getAppPackageList(@PathVariable("appID") String appID) {
AppViewModel appViewModel = this.appService.getById(appID);
public Map<String, Object> getAppPackageList(@PathVariable("appID") String appID, HttpServletRequest request) {
Subject currentUser = SecurityUtils.getSubject();
User user = (User) currentUser.getPrincipal();
AppViewModel appViewModel = this.appService.getById(appID, user, request);
Map<String, Object> map = new HashMap<>();
try {
map.put("packages", appViewModel.getPackageList());
@@ -70,23 +71,24 @@ public class AppController {
return map;
}
@RequiresPermissions("/app/delete")
// @RequiresPermissions("/app/delete")
@RequestMapping("/app/delete/{id}")
@ResponseBody
public BaseResponse deleteById(@PathVariable("id") String id) {
public BaseResponse deleteById(@PathVariable("id") String id, HttpServletRequest request) {
try {
Subject currentUser = SecurityUtils.getSubject();
User user = (User) currentUser.getPrincipal();
if (user == null) {
return ResponseUtil.unauthz();
}
AppViewModel viewModel = this.appService.getById(id);
AppViewModel viewModel = this.appService.getById(id, user, request);
if (viewModel.getUserId().equals(user.getId())) {
this.appService.deleteById(id);
return ResponseUtil.ok("删除成功");
}
return ResponseUtil.unauthz();
} catch (Exception e) {
e.printStackTrace();
return ResponseUtil.fail();
}
}
@@ -7,6 +7,9 @@ import org.apache.commons.io.FilenameUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
@@ -50,6 +53,10 @@ public class PackageController {
private PathManager pathManager;
@Resource
private UserService userService;
@Resource
private StorageUtil storageUtil;
@Resource
private StorageService storageService;
/**
* 预览页
@@ -61,10 +68,10 @@ public class PackageController {
@GetMapping("/s/{code}")
public String get(@PathVariable("code") String code, HttpServletRequest request) {
String id = request.getParameter("id");
AppViewModel viewModel = this.appService.findByCode(code, id);
AppViewModel viewModel = this.appService.findByCode(code, id, request);
request.setAttribute("app", viewModel);
request.setAttribute("ca_path", this.pathManager.getCAPath());
request.setAttribute("basePath", this.pathManager.getBaseURL(false));
request.setAttribute("ca_path", PathManager.request(request).getCAPath());
request.setAttribute("basePath", PathManager.request(request).getBaseURL() + "/");
return "install";
}
@@ -77,7 +84,7 @@ public class PackageController {
*/
@GetMapping("/devices/{id}")
public String devices(@PathVariable("id") String id, HttpServletRequest request) {
PackageViewModel viewModel = this.packageService.findById(id);
PackageViewModel viewModel = this.packageService.findById(id, request);
request.setAttribute("app", viewModel);
return "devices";
}
@@ -112,17 +119,16 @@ public class PackageController {
Subject currentUser = SecurityUtils.getSubject();
user = (User) currentUser.getPrincipal();
}
// 无用户信息不允许上传
if (user == null) {
return ResponseUtil.unauthz();
}
String filePath = StorageUtil.checkAndTransfer(file.getInputStream(), file.getSize(), file.getContentType(), file.getOriginalFilename());
// 检测文件
String filePath = storageUtil.checkAndTransfer(file.getInputStream(), file.getContentType(), file.getOriginalFilename());
if (filePath == null) {
return ResponseUtil.fail(401, "不支持的文件类型");
}
Package aPackage = this.packageService.buildPackage(filePath, user);
// 获取扩展参数
Map<String, String> extra = new HashMap<>();
String jobName = request.getParameter("jobName");
String buildNumber = request.getParameter("buildNumber");
@@ -132,15 +138,13 @@ public class PackageController {
if (StringUtils.hasLength(buildNumber)) {
extra.put("buildNumber", buildNumber);
}
if (!extra.isEmpty()) {
aPackage.setExtra(JSON.toJSONString(extra));
}
App app = this.appService.savePackage(aPackage, user);
// URL
String codeURL = this.pathManager.getBaseURL(false) + "p/code/" + app.getCurrentPackage().getId();
// 发送WebHook消息
WebHookClient.sendMessage(app, pathManager);
return ResponseUtil.ok(codeURL);
Package aPackage = this.packageService.save(filePath, extra, user);
// App app = this.appService.savePackage(aPackage, user);
// // URL
// String codeURL = this.pathManager.getBaseURL(false) + "p/code/" + app.getCurrentPackage().getId();
// // 发送WebHook消息
// WebHookClient.sendMessage(app, pathManager);
return ResponseUtil.ok();
} catch (Exception e) {
e.printStackTrace();
return ResponseUtil.badArgument();
@@ -154,34 +158,34 @@ public class PackageController {
* @param response
*/
@RequestMapping("/p/{id}")
public void download(@PathVariable("id") String id, HttpServletResponse response) {
public ResponseEntity<org.springframework.core.io.Resource> download(@PathVariable("id") String id, HttpServletResponse response) {
try {
Package aPackage = this.packageService.get(id);
String path = PathManager.getFullPath(aPackage) + aPackage.getFileName();
File file = new File(path);
if (file.exists()) { //判断文件父目录是否存在
response.setContentType("application/force-download");
// 文件名称转换
String fileName = aPackage.getName() + "_" + aPackage.getVersion();
String ext = "." + FilenameUtils.getExtension(aPackage.getFileName());
String appName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
response.setHeader("Content-Disposition", "attachment;fileName=" + appName + ext);
byte[] buffer = new byte[1024];
OutputStream os = response.getOutputStream();
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer);
i = bis.read(buffer);
}
bis.close();
fis.close();
String key = aPackage.getSourceFile().getKey();
Storage storage = storageService.findByKey(key);
if (key == null) {
return ResponseEntity.notFound().build();
}
if (key.contains("../")) {
return ResponseEntity.badRequest().build();
}
String type = storage.getType();
MediaType mediaType = MediaType.parseMediaType(type);
org.springframework.core.io.Resource file = storageUtil.loadAsResource(key);
if (file == null) {
return ResponseEntity.notFound().build();
}
// 文件名称转换
String fileName = aPackage.getName() + "_" + aPackage.getVersion();
String ext = "." + FilenameUtils.getExtension(aPackage.getFileName());
String appName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
return ResponseEntity.ok().contentType(mediaType).header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + appName + ext + "\"").body(file);
} catch (Exception e) {
e.printStackTrace();
}
return ResponseEntity.notFound().build();
}
/**
@@ -191,9 +195,9 @@ public class PackageController {
* @param response
*/
@RequestMapping("/m/{id}")
public void getManifest(@PathVariable("id") String id, HttpServletResponse response) {
public void getManifest(@PathVariable("id") String id, HttpServletRequest request, HttpServletResponse response) {
try {
PackageViewModel viewModel = this.packageService.findById(id);
PackageViewModel viewModel = this.packageService.findById(id, request);
if (viewModel != null && viewModel.isiOS()) {
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment;fileName=manifest.plist");
@@ -212,9 +216,9 @@ public class PackageController {
* @param response
*/
@RequestMapping("/p/code/{id}")
public void getQrCode(@PathVariable("id") String id, HttpServletResponse response) {
public void getQrCode(@PathVariable("id") String id, HttpServletRequest request, HttpServletResponse response) {
try {
PackageViewModel viewModel = this.packageService.findById(id);
PackageViewModel viewModel = this.packageService.findById(id, request);
if (viewModel != null) {
response.setContentType("image/png");
QRCodeUtil.encode(viewModel.getPreviewURL()).withSize(250, 250).writeTo(response.getOutputStream());
@@ -244,29 +248,4 @@ public class PackageController {
return map;
}
/**
* 转存文件
*
* @param srcFile
* @return
*/
private String transfer(MultipartFile srcFile) {
try {
// 获取文件后缀
String fileName = srcFile.getOriginalFilename();
String ext = FilenameUtils.getExtension(fileName);
// 生成文件名
String newFileName = UUID.randomUUID().toString() + "." + ext;
// 转存到 tmp
String destPath = FileUtils.getTempDirectoryPath() + File.separator + newFileName;
destPath = destPath.replaceAll("//", "/");
srcFile.transferTo(new File(destPath));
return destPath;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
@@ -72,6 +72,10 @@ public class UserController {
if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
return ResponseUtil.badArgument();
}
User u = this.userService.findByUsername(username);
if (u != null) {
return ResponseUtil.fail(100, username + "已被注册");
}
user = this.userService.createUser(username, password);
return login(request, username, password);
}
+6 -2
View File
@@ -1,9 +1,13 @@
package org.yzr.dao;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.yzr.model.Permission;
import org.yzr.model.User;
import java.util.List;
public interface PermissionDao extends CrudRepository<Permission, String> {
@Query("select p from Permission p where p.permission=:permission and p.role.id=:roleId")
List<Permission> findByPermission(@Param("permission") String permission, @Param("roleId") String roleId);
}
+3 -1
View File
@@ -5,7 +5,9 @@ import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.yzr.model.Role;
import java.util.List;
public interface RoleDao extends CrudRepository<Role, String> {
@Query("select r from Role r where r.name=:name")
Role findByName(@Param("name") String name);
List<Role> findByName(@Param("name") String name);
}
+1 -1
View File
@@ -39,7 +39,7 @@ public class App {
// 当前包
@JoinColumn(name = "currentID", referencedColumnName = "id")
private Package currentPackage;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name = "userId")
private User owner;
+37 -9
View File
@@ -5,15 +5,19 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.yzr.dao.AppDao;
import org.yzr.dao.PackageDao;
import org.yzr.dao.StorageDao;
import org.yzr.dao.UserDao;
import org.yzr.model.App;
import org.yzr.model.Package;
import org.yzr.model.Storage;
import org.yzr.model.User;
import org.yzr.storage.StorageUtil;
import org.yzr.utils.CharUtil;
import org.yzr.utils.file.PathManager;
import org.yzr.vo.AppViewModel;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
@@ -29,6 +33,10 @@ public class AppService {
private PackageDao packageDao;
@Resource
private PathManager pathManager;
@Resource
private StorageDao storageDao;
@Resource
private StorageUtil storageUtil;
@Transactional
public App save(App app, User user) {
@@ -46,24 +54,32 @@ public class AppService {
}
@Transactional
public List<AppViewModel> findAll() {
public List<AppViewModel> findAll(HttpServletRequest request) {
Iterable<App> apps = this.appDao.findAll();
List<AppViewModel> list = new ArrayList<>();
for (App app : apps) {
AppViewModel appViewModel = new AppViewModel(app, this.pathManager, false);
AppViewModel appViewModel = new AppViewModel(app, request, false);
list.add(appViewModel);
}
return list;
}
@Transactional
public AppViewModel getById(String appID) {
public AppViewModel getById(String appID, User user, HttpServletRequest request) {
Optional<App> optionalApp = this.appDao.findById(appID);
App app = optionalApp.get();
if (!app.getOwner().getId().equalsIgnoreCase(user.getId())) {
return null;
}
if (app != null) {
app.getPackageList().forEach(aPackage -> {
try{
aPackage.getSourceFile().getKey();
aPackage.getIconFile().getKey();
} catch (Exception e) {}
});
AppViewModel appViewModel = new AppViewModel(app, this.pathManager, true);
AppViewModel appViewModel = new AppViewModel(app, request, true);
return appViewModel;
}
return null;
@@ -87,7 +103,8 @@ public class AppService {
// 级联查询
app.getPackageList().forEach(aPackage1 -> {
});
app.getWebHookList().forEach(webHook -> {});
app.getWebHookList().forEach(webHook -> {
});
}
app.setName(aPackage.getName());
app.getPackageList().add(aPackage);
@@ -100,7 +117,18 @@ public class AppService {
public void deleteById(String id) {
App app = this.appDao.findById(id).get();
if (app != null) {
app.getPackageList().forEach(aPackage ->{
Storage iconFile = aPackage.getIconFile();
this.storageUtil.delete(iconFile.getKey());
this.storageDao.deleteById(iconFile.getId());
Storage sourceFile = aPackage.getSourceFile();
this.storageUtil.delete(sourceFile.getKey());
this.storageDao.deleteById(sourceFile.getId());
this.packageDao.deleteById(aPackage.getId());
});
this.appDao.deleteById(id);
// 消除整个 APP 目录
String path = PathManager.getAppPath(app);
PathManager.deleteDirectory(path);
@@ -115,18 +143,18 @@ public class AppService {
* @return
*/
@Transactional
public AppViewModel findByCode(String code, String packageId) {
public AppViewModel findByCode(String code, String packageId, HttpServletRequest request) {
App app = this.appDao.findByShortCode(code);
AppViewModel viewModel = new AppViewModel(app, pathManager, packageId);
AppViewModel viewModel = new AppViewModel(app, request, packageId);
return viewModel;
}
@Transactional
public List<AppViewModel> findByUser(User user) {
public List<AppViewModel> findByUser(User user, HttpServletRequest request) {
Iterable<App> apps = this.appDao.findByUser(user);
List<AppViewModel> list = new ArrayList<>();
for (App app : apps) {
AppViewModel appViewModel = new AppViewModel(app, this.pathManager, false);
AppViewModel appViewModel = new AppViewModel(app, request, false);
list.add(appViewModel);
}
return list;
@@ -3,19 +3,31 @@ package org.yzr.service;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.yzr.dao.AppDao;
import org.yzr.dao.PackageDao;
import org.yzr.dao.UserDao;
import org.yzr.model.App;
import org.yzr.model.Package;
import org.yzr.model.Storage;
import org.yzr.model.User;
import org.yzr.storage.StorageUtil;
import org.yzr.utils.CharUtil;
import org.yzr.utils.file.FileType;
import org.yzr.utils.file.PathManager;
import org.yzr.utils.image.ImageUtils;
import org.yzr.utils.parser.ParserClient;
import org.yzr.vo.PackageViewModel;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.UUID;
@Service
public class PackageService {
@@ -24,38 +36,12 @@ public class PackageService {
private PackageDao packageDao;
@Resource
private PathManager pathManager;
public Package buildPackage(String filePath, User user) throws ClassNotFoundException {
Package aPackage = ParserClient.parse(filePath);
try {
App app = new App();
app.setOwner(user);
aPackage.setApp(app);
String fileName = aPackage.getPlatform() + "." + FilenameUtils.getExtension(filePath);
// 更新文件名
aPackage.setFileName(fileName);
String packagePath = PathManager.getFullPath(aPackage);
String tempIconPath = PathManager.getTempIconPath(aPackage);
String iconPath = packagePath + File.separator + "icon.png";
String sourcePath = packagePath + File.separator + fileName;
// 拷贝图标
ImageUtils.resize(tempIconPath, iconPath, 192, 192);
// 源文件
FileUtils.copyFile(new File(filePath), new File(sourcePath));
// 删除临时图标
FileUtils.forceDelete(new File(tempIconPath));
// 源文件
FileUtils.forceDelete(new File(filePath));
} catch (Exception e) {
e.printStackTrace();
}
aPackage.setApp(null);
return aPackage;
}
@Resource
private UserDao userDao;
@Resource
private AppDao appDao;
@Resource
private StorageUtil storageUtil;
@Transactional
public Package save(Package aPackage) {
@@ -67,13 +53,14 @@ public class PackageService {
Package aPackage = this.packageDao.findById(id).get();
// 级联查询用户
aPackage.getApp().getOwner().getId();
aPackage.getSourceFile().getKey();
return aPackage;
}
@Transactional
public PackageViewModel findById(String id) {
public PackageViewModel findById(String id, HttpServletRequest request) {
Package aPackage = this.packageDao.findById(id).get();
PackageViewModel viewModel = new PackageViewModel(aPackage, this.pathManager);
PackageViewModel viewModel = new PackageViewModel(aPackage, request);
return viewModel;
}
@@ -87,4 +74,68 @@ public class PackageService {
}
}
@Transactional
public Package save(String filePath, Map<String, String> extra, User user) throws Exception {
Package aPackage = ParserClient.parse(filePath);
String fileName = aPackage.getPlatform() + "." + FilenameUtils.getExtension(filePath);
// 更新文件名
aPackage.setFileName(fileName);
// 获取用户信息
user = this.userDao.findById(user.getId()).get();
// 设置用户信息
App app = this.appDao.getByBundleIDAndPlatformAndOwner(aPackage.getBundleID(), aPackage.getPlatform(), user);
if (app == null) {
app = new App();
String shortCode = CharUtil.generate(4);
while (this.appDao.findByShortCode(shortCode) != null) {
shortCode = CharUtil.generate(4);
}
BeanUtils.copyProperties(aPackage, app);
app.setShortCode(shortCode);
app.setOwner(user);
} else {
// 级联查询
app.getPackageList().forEach(aPackage1 -> {
});
app.getWebHookList().forEach(webHook -> {});
}
aPackage.setApp(app);
String packagePath = PathManager.getFullPath(aPackage);
String tempIconPath = PathManager.getTempIconPath(aPackage);
String sourcePath = packagePath + File.separator + fileName;
// 获取文件后缀
String ext = FilenameUtils.getExtension(fileName);
// 生成文件名
String newFileName = UUID.randomUUID().toString() + ".png";
// 转存到 tmp
String iconPath = FileUtils.getTempDirectoryPath() + File.separator + newFileName;
iconPath = iconPath.replaceAll("//", "/");
// 拷贝图标
ImageUtils.resize(tempIconPath, iconPath, 192, 192);
// 源文件
FileUtils.copyFile(new File(filePath), new File(sourcePath));
// 删除临时图标
FileUtils.forceDelete(new File(tempIconPath));
// 源文件
FileUtils.forceDelete(new File(filePath));
File sourceFile = new File(sourcePath);
File iconFile = new File(iconPath);
Storage storage = storageUtil.store(new FileInputStream(sourceFile), sourceFile.length(), "application/octet-stream", fileName);
Storage iconStorage = storageUtil.store(new FileInputStream(iconFile), iconFile.length(), "application/x-png", iconFile.getName());
// 删除临时图标
FileUtils.forceDelete(sourceFile);
// 源文件
FileUtils.forceDelete(iconFile);
aPackage.setIconFile(iconStorage);
aPackage.setSourceFile(storage);
aPackage = this.packageDao.save(aPackage);
app.setName(aPackage.getName());
app.getPackageList().add(aPackage);
app.setCurrentPackage(aPackage);
this.appDao.save(app);
return aPackage;
}
}
+38 -15
View File
@@ -109,12 +109,15 @@ public class UserService {
user.setPassword(encoder.encode(password));
user.setCreateTime(System.currentTimeMillis());
Role role = this.roleDao.findByName("管理员");
Set<Role> roleList = new HashSet<>();
roleList.add(role);
user.setRoleList(roleList);
updateToken(user);
this.userDao.save(user);
List<Role> adminList = this.roleDao.findByName("管理员");
if (adminList != null && adminList.size() > 0) {
Role role = adminList.get(0);
Set<Role> roleList = new HashSet<>();
roleList.add(role);
user.setRoleList(roleList);
updateToken(user);
this.userDao.save(user);
}
return user;
}
@@ -125,22 +128,38 @@ public class UserService {
if (this.userDao.findByUsername(username) == null) {
long currentTime = System.currentTimeMillis();
Role role = new Role();
role.setCreateTime(currentTime);
role.setDescription("管理员");
role.setName("管理员");
role.setEnabled(true);
this.roleDao.save(role);
List<Role> adminList = this.roleDao.findByName("管理员");
if (adminList != null && adminList.size() > 0) {
role = adminList.get(0);
} else {
role.setCreateTime(currentTime);
role.setDescription("管理员");
role.setName("管理员");
role.setEnabled(true);
this.roleDao.save(role);
}
List<Permission> permissionList = new ArrayList<>();
String[] perms = new String[]{
"/apps",
"/apps/get",
// "/apps/delete",
"/apps/delete",
"/packageList/get"
};
for (String string : perms) {
Permission permission = new Permission();
permission.setCreateTime(currentTime);
Permission permission = null;
List<Permission> permissions = this.permissionDao.findByPermission(string, role.getId());
if (permissions != null) {
for (int i = 0; i < permissions.size(); i++) {
if (permissions.get(i).getRole().getId().equalsIgnoreCase(role.getId())) {
permission = permissions.get(i);
break;
}
}
}
if (permission == null) {
permission = new Permission();
permission.setCreateTime(currentTime);
}
permission.setPermission(string);
permission.setUpdateTime(currentTime);
permission.setRole(role);
@@ -162,4 +181,8 @@ public class UserService {
this.userDao.save(user);
}
}
public User findByUsername(String username) {
return this.userDao.findByUsername(username);
}
}
+11 -38
View File
@@ -4,6 +4,7 @@ import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.yzr.model.Storage;
import org.yzr.utils.CharUtil;
@@ -49,27 +50,12 @@ public class StorageUtil {
/**
* 检测并转存文件
* @param inputStream
* @param contentLength
* @param contentType
* @param fileName
* @return
*/
public static String checkAndTransfer(InputStream inputStream, long contentLength, String contentType, String fileName) {
// 判断文件类型
if (!(contentType != null && contentType.equalsIgnoreCase("application/octet-stream"))) {
return null;
}
int len = 28;
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream, len);
public String checkAndTransfer(InputStream inputStream, String contentType, String fileName) {
try {
byte[] b = new byte[len];
FileType type = FileUtil.getType(pushbackInputStream);
// ipa和apk文件都是zip文件
if (type != FileType.ZIP) {
pushbackInputStream.close();
return null;
}
pushbackInputStream.unread(b);
// 获取文件后缀
String ext = FilenameUtils.getExtension(fileName);
// 生成文件名
@@ -77,8 +63,14 @@ public class StorageUtil {
// 转存到 tmp
String destPath = FileUtils.getTempDirectoryPath() + File.separator + newFileName;
destPath = destPath.replaceAll("//", "/");
System.out.println(destPath);
Files.copy(pushbackInputStream, Paths.get(destPath), StandardCopyOption.REPLACE_EXISTING);
Files.copy(inputStream, Paths.get(destPath), StandardCopyOption.REPLACE_EXISTING);
FileType type = FileUtil.getType(destPath);
// ipa和apk文件都是zip文件
if (type != FileType.ZIP) {
// 删除文件
FileUtils.forceDelete(new File(destPath));
return null;
}
return destPath;
} catch (Exception e) {
e.printStackTrace();
@@ -95,27 +87,8 @@ public class StorageUtil {
* @param fileName 文件索引名
*/
public Storage store(InputStream inputStream, long contentLength, String contentType, String fileName) {
// 判断文件类型
if (!(contentType != null && contentType.equalsIgnoreCase("application/octet-stream"))) {
return null;
}
String key = generateKey(fileName);
int len = 28;
PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream, len);
try {
byte[] b = new byte[len];
FileType type = FileUtil.getType(pushbackInputStream);
// ipa和apk文件都是zip文件
if (type != FileType.ZIP) {
pushbackInputStream.close();
return null;
}
pushbackInputStream.unread(b);
} catch (Exception e) {
e.printStackTrace();
}
storage.store(pushbackInputStream, contentLength, contentType, key);
storage.store(inputStream, contentLength, contentType, key);
String url = generateUrl(key);
Storage storageInfo = new Storage();
@@ -8,6 +8,7 @@ import org.yzr.model.App;
import org.yzr.model.Package;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.net.InetAddress;
@@ -18,6 +19,23 @@ public class PathManager {
private Environment environment;
private String httpsBaseURL;
private String httpBaseURL;
private String host;
private String scheme = "http";
public static PathManager request(HttpServletRequest request) {
PathManager pathManager = new PathManager();
pathManager.host = request.getHeader("host");
return pathManager;
}
public PathManager useHttps() {
this.scheme = "https";
return this;
}
public String getBaseURL() {
return this.scheme + "://" + this.host;
}
/**
* 获取图标的临时路径
@@ -110,55 +128,6 @@ public class PathManager {
}
}
/**
* 获取基础路径
*
* @param isHttps
* @return
*/
public String getBaseURL(boolean isHttps) {
if (isHttps) {
if (httpsBaseURL != null) {
return httpsBaseURL;
}
} else {
if (httpBaseURL != null) {
return httpBaseURL;
}
}
try {
// URL
InetAddress address = InetAddress.getLocalHost();
String domain = environment.getProperty("server.domain");
if (domain == null) {
domain = address.getHostAddress();
}
int httpPort = Integer.parseInt(environment.getProperty("server.http.port"));
int httpsPort = Integer.parseInt(environment.getProperty("server.port"));
int port = isHttps ? httpsPort : httpPort;
String protocol = isHttps ? "https" : "http";
String portString = ":" + port;
if (port == 80 || port == 443) {
portString = "";
}
String baseURL = protocol + "://" + domain + portString + "/";
//解决重复读配置文件
if (isHttps) {
httpsBaseURL = baseURL;
} else {
httpBaseURL = baseURL;
}
return baseURL;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取包所在路径
*
@@ -167,10 +136,12 @@ public class PathManager {
* @return
*/
public String getPackageResourceURL(Package aPackage, boolean isHttps) {
String baseURL = getBaseURL(isHttps);
String resourceURL = baseURL + aPackage.getPlatform() + "/" + aPackage.getBundleID()
+ "/" + aPackage.getCreateTime() + "/";
return resourceURL;
// getBaseURL() + "/fetch/" + aPackage.getSourceFile().getKey();
// String baseURL = getBaseURL(isHttps);
// String resourceURL = baseURL + aPackage.getPlatform() + "/" + aPackage.getBundleID()
// + "/" + aPackage.getCreateTime() + "/";
// return resourceURL;
return null;
}
/**
@@ -179,6 +150,6 @@ public class PathManager {
* @return
*/
public String getCAPath() {
return getBaseURL(false) + "crt/ca.crt";
return getBaseURL() + "/crt/ca.crt";
}
}
@@ -51,8 +51,8 @@ public class DingDingWebHook implements IWebHook {
}
Map<String, Object> markdown = new HashMap<>();
markdown.put("title", app.getName());
String currentPackageURL = pathManager.getBaseURL(false) + "s/" + app.getShortCode() + "?id=" + app.getCurrentPackage().getId();
String appURL = pathManager.getBaseURL(false) + "apps/" + app.getId();
String currentPackageURL = "/s/" + app.getShortCode() + "?id=" + app.getCurrentPackage().getId();
String appURL = "/apps/" + app.getId();
String platform = "iOS";
if (app.getPlatform().equalsIgnoreCase("android")) {
platform = "Android";
+15 -12
View File
@@ -4,6 +4,7 @@ import org.yzr.model.App;
import org.yzr.model.Package;
import org.yzr.utils.file.PathManager;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
@@ -39,43 +40,45 @@ public class AppViewModel {
/***
* 初始化是否加载列表
* @param app
* @param pathManager
* @param request
* @param loadList
*/
public AppViewModel(App app, PathManager pathManager, boolean loadList) {
public AppViewModel(App app, HttpServletRequest request, boolean loadList) {
String httpURL = PathManager.request(request).getBaseURL();
this.id = app.getId();
this.platform = app.getPlatform();
this.bundleID = app.getBundleID();
app.getCurrentPackage().setApp(app);
this.userId = app.getOwner().getId();
this.icon = PathManager.getRelativePath(app.getCurrentPackage()) + "icon.png";
this.icon = httpURL + "/fetch/" + app.getCurrentPackage().getIconFile().getKey();
Package aPackage = findPackageById(app, null);
this.version = aPackage.getVersion();
this.buildVersion = aPackage.getBuildVersion();
this.shortCode = app.getShortCode();
this.name = app.getName();
this.installPath = pathManager.getBaseURL(false) + "s/" + app.getShortCode();
this.installPath = httpURL + "/s/" + app.getShortCode();
this.minVersion = aPackage.getMinVersion();
this.currentPackage = new PackageViewModel(aPackage, pathManager);
this.currentPackage = new PackageViewModel(aPackage, request);
if (loadList) {
// 排序
this.packageList = sortPackages(app.getPackageList(), pathManager);
this.packageList = sortPackages(app.getPackageList(), request);
}
}
public AppViewModel(App app, PathManager pathManager, String packageId) {
public AppViewModel(App app, HttpServletRequest request, String packageId) {
String httpURL = PathManager.request(request).getBaseURL();
this.id = app.getId();
this.platform = app.getPlatform();
this.bundleID = app.getBundleID();
this.icon = PathManager.getRelativePath(app.getCurrentPackage()) + "icon.png";
this.icon = httpURL + "/fetch/" + app.getCurrentPackage().getIconFile().getKey();
Package aPackage = findPackageById(app, packageId);
this.version = aPackage.getVersion();
this.buildVersion = aPackage.getBuildVersion();
this.shortCode = app.getShortCode();
this.name = app.getName();
this.installPath = pathManager.getBaseURL(false) + "s/" + app.getShortCode();
this.installPath = httpURL + "/s/" + app.getShortCode();
this.minVersion = aPackage.getMinVersion();
this.currentPackage = new PackageViewModel(aPackage, pathManager);
this.currentPackage = new PackageViewModel(aPackage, request);
}
private static Package findPackageById(App app, String id) {
@@ -90,11 +93,11 @@ public class AppViewModel {
return app.getCurrentPackage();
}
private static List<PackageViewModel> sortPackages(List<Package> packages, PathManager pathManager) {
private static List<PackageViewModel> sortPackages(List<Package> packages, HttpServletRequest request) {
// 排序
List<PackageViewModel> packageViewModels = new ArrayList<>();
for (Package aPackage : packages) {
PackageViewModel packageViewModel = new PackageViewModel(aPackage, pathManager);
PackageViewModel packageViewModel = new PackageViewModel(aPackage, request);
packageViewModels.add(packageViewModel);
}
packageViewModels.sort((o1, o2) -> {
+12 -7
View File
@@ -7,6 +7,7 @@ import org.yzr.model.Package;
import org.yzr.utils.date.DateUtil;
import org.yzr.utils.file.PathManager;
import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.time.ZoneOffset;
import java.util.Arrays;
@@ -36,10 +37,11 @@ public class PackageViewModel {
private int deviceCount;
private String message;
public PackageViewModel(Package aPackage, PathManager pathManager) {
this.downloadURL = pathManager.getBaseURL(false) + "p/" + aPackage.getId();
this.safeDownloadURL = pathManager.getBaseURL(true) + "p/" + aPackage.getId();
this.iconURL = pathManager.getPackageResourceURL(aPackage, true) + "icon.png";
public PackageViewModel(Package aPackage, HttpServletRequest request) {
String httpURL = PathManager.request(request).getBaseURL();
String httpsURL = PathManager.request(request).useHttps().getBaseURL();
this.downloadURL = httpURL + "/p/" + aPackage.getId();
this.safeDownloadURL = httpsURL + "/p/" + aPackage.getId();
this.id = aPackage.getId();
this.version = aPackage.getVersion();
this.bundleID = aPackage.getBundleID();
@@ -52,7 +54,7 @@ public class PackageViewModel {
this.displayTime = displayTime;
if (aPackage.getPlatform().equals("ios")) {
this.iOS = true;
String url = pathManager.getBaseURL(true) + "m/" + aPackage.getId();
String url = httpsURL + "/m/" + aPackage.getId();
try {
this.installURL = "itms-services://?action=download-manifest&url=" + URLEncoder.encode(url, "utf-8");
} catch (Exception e) {
@@ -60,9 +62,9 @@ public class PackageViewModel {
}
} else if (aPackage.getPlatform().equals("android")) {
this.iOS = false;
this.installURL = pathManager.getPackageResourceURL(aPackage, false) + aPackage.getFileName();
this.installURL = httpURL + "/p/" + aPackage.getId();
}
this.previewURL = pathManager.getBaseURL(false) + "s/" + aPackage.getApp().getShortCode() + "?id=" + aPackage.getId();
this.previewURL = httpURL + "/s/" + aPackage.getApp().getShortCode() + "?id=" + aPackage.getId();
if (this.isiOS()) {
if (aPackage.getProvision() == null) {
this.type = "内测版";
@@ -96,6 +98,9 @@ public class PackageViewModel {
}
}
this.message = message;
try {
this.iconURL = httpsURL + "/fetch/" + aPackage.getIconFile().getKey();
} catch (Exception e){}
}
public String getDownloadURL() {
+2 -2
View File
@@ -43,7 +43,7 @@ storage.active=local
# 本地对象存储配置信息
storage.local.storagePath=storage
# 这个地方应该是wx模块的WxStorageController的fetch方法对应的地址
storage.local.address=http://localhost:8080/app/storage/fetch/
storage.local.address=http://127.0.0.1/fetch/
# 阿里云对象存储配置信息
storage.aliyun.endpoint=oss-cn-shenzhen.aliyuncs.com
storage.aliyun.accessKeyId=111111
@@ -63,7 +63,7 @@ storage.qiniu.bucketName=app_manager
# 自定义配置
server.port=443
server.http.port=80
server.http.port=8080
config.debug=debug
server.domain=127.0.0.1
admin.username=admin
+6 -6
View File
@@ -35,7 +35,7 @@
</h1>
<i class="icon-angle-right"></i>
<div class="navbar-title primary-title">
<a class="ng-binding" th:href="${baseURL} + 'apps'">我的应用</a>
<a class="ng-binding" th:href="${baseURL} + '/apps'">我的应用</a>
</div>
<i class="icon-angle-right ng-hide"></i>
</nav>
@@ -73,17 +73,17 @@
<i th:class="'type-icon ' + @{'icon-' + ${app.platform}}"></i>
<div class="type-mark"></div>
<a class="appicon" th:href="'/apps/' + ${app.id}" target="_blank">
<img class="icon ng-isolate-scope" width="100" height="100" th:src="@{'/' + ${app.icon}}"/>
<img class="icon ng-isolate-scope" width="100" height="100" th:src="${app.icon}"/>
</a>
<!-- ngIf: app.has_combo --><br>
<p class="appname" th:data="@{${baseURL} + 'apps/' + ${app.id}}">
<p class="appname" th:data="@{${baseURL} + '/apps/' + ${app.id}}">
<i class="icon-owner"></i>
<span class="ng-binding">[[${app.name}]]</span></p>
<table>
<tbody>
<tr>
<td class="ng-binding">短链接:</td>
<td><span class="ng-binding">[[${baseURL}]]s/[[${app.shortCode}]]</span></td>
<td><span class="ng-binding">[[${baseURL}]]/s/[[${app.shortCode}]]</span></td>
</tr>
<tr>
<td class="ng-binding">包名:</td>
@@ -102,7 +102,7 @@
<div class="action">
<a class="ng-binding" th:href="'/apps/' + ${app.id}">
<i class="icon-pen"></i> 编辑</a>
<a th:href="@{${baseURL}+'s/'+${app.shortCode}}" target="_blank" class="ng-binding">
<a th:href="@{${baseURL}+'/s/'+${app.shortCode}}" target="_blank" class="ng-binding">
<i class="icon-eye"></i> 预览</a>
<button class="btn btn-remove ng-scope" th:data="${app.id}">
<i class="icon icon-trash"></i>
@@ -138,7 +138,7 @@
var file = files[0]
//上传
var xhr = new XMLHttpRequest();
xhr.open("post", "/upload", true);
xhr.open("post", "/app/upload", true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
// 获取上传进度
xhr.upload.onprogress = function (event) {
+1 -1
View File
@@ -37,7 +37,7 @@
<div class="icon-container wrapper">
<i class="icon-icon_path bg-path"></i>
<span class="icon">
<img th:src="@{'/' + ${app.icon}}" itemprop="image">
<img th:src="${app.icon}" itemprop="image">
</span>
<span class="qrcode" id="qrcode" th:data="${app.currentPackage.previewURL}">
</span>
+2 -2
View File
@@ -57,7 +57,7 @@
<div class="banner has-devices">
<div class="middle-wrapper clearfix">
<div id="app-activity-icon" class="pull-left icon-container appicon">
<img th:src="'/' + ${package.icon}" width="100" height="100" class="change_icon ng-isolate-scope" />
<img th:src="${package.icon}" width="100" height="100" class="change_icon ng-isolate-scope" />
</div>
<div class="badges">
<span tooltip-top="" tooltip="复制到剪贴板" id="js-app-short-copy-trigger"
@@ -122,7 +122,7 @@
应用图标
</div>
<div class="icon_select unploadIcon appicon" style="width: 100px; cursor: pointer">
<img width="100" height="100" id="icon_img" style="border-radius: 17%" class="change_icon ng-isolate-scope" th:src="'/' + ${package.icon}">
<img width="100" height="100" id="icon_img" style="border-radius: 17%" class="change_icon ng-isolate-scope" th:src="${package.icon}">
</div>
</div>
<div class="field app-deletion">