新增office文档创建,在线预览,编辑

This commit is contained in:
马超 2021-07-08 19:50:14 +08:00
parent 1addde3ac7
commit 3578ec5f7f
19 changed files with 1908 additions and 9 deletions

10
pom.xml
View File

@ -6,12 +6,12 @@
<parent>
<groupId>com.qiwenshare</groupId>
<artifactId>qiwenshare</artifactId>
<version>1.0.3</version>
<version>1.0.4</version>
</parent>
<groupId>com.qiwenshare</groupId>
<artifactId>qiwen-file</artifactId>
<version>1.0.3-SNAPSHOT</version>
<version>1.0.4-SNAPSHOT</version>
<name>qiwen-file</name>
<description>fileos.qiwenshare.com</description>
<packaging>jar</packaging>
@ -110,6 +110,12 @@
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>com.inversoft</groupId>
<artifactId>prime-jwt</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>

View File

@ -11,6 +11,7 @@ import java.util.Map;
public interface IUserFileService extends IService<UserFile> {
List<UserFile> selectUserFileByNameAndPath(String fileName, String filePath, Long userId);
List<UserFile> selectSameUserFile(String fileName, String filePath, String extendName, Long userId);
void replaceUserFilePath(String filePath, String oldFilePath, Long userId);
List<FileListVo> userFileList(UserFile userFile, Long beginCount, Long pageCount);
void updateFilepathByFilepath(String oldfilePath, String newfilePath, String fileName, String extendName, long userId);

View File

@ -44,16 +44,14 @@ public class WebMvcConfig implements WebMvcConfigurer {
list.add("/file/**");
list.add("/filetransfer/**");
list.add("/recoveryfile/**");
list.add("/share/**");
list.add("/share/sharefile");
list.add("/share/savesharefile");
list.add("/share/shareList");
registry.addInterceptor(authenticationInterceptor)
.addPathPatterns(list)
.excludePathPatterns("/file",
"/filetransfer/downloadfile",
"/filetransfer/preview",
"/share/sharefileList",
"/share/sharetype",
"/share/checkextractioncode",
"/share/checkendtime");
"/filetransfer/preview");
}
}

View File

@ -0,0 +1,331 @@
package com.qiwenshare.file.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiwenshare.common.exception.NotLoginException;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.file.anno.MyLog;
import com.qiwenshare.file.api.IFileService;
import com.qiwenshare.file.api.IFiletransferService;
import com.qiwenshare.file.api.IUserFileService;
import com.qiwenshare.file.api.IUserService;
import com.qiwenshare.file.domain.*;
import com.qiwenshare.file.dto.file.CreateOfficeFileDTO;
import com.qiwenshare.file.dto.file.EditOfficeFileDTO;
import com.qiwenshare.file.dto.file.PreviewOfficeFileDTO;
import com.qiwenshare.file.helper.ConfigManager;
import com.qiwenshare.ufo.factory.UFOFactory;
import com.qiwenshare.ufo.operation.write.Writer;
import com.qiwenshare.ufo.operation.write.domain.WriteFile;
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;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import java.util.UUID;
@Tag(name = "office", description = "该接口为Onlyoffice文件操作接口主要用来做一些文档的编辑浏览等。")
@RestController
@Slf4j
@RequestMapping({"/office"})
public class OfficeController {
public static final String CURRENT_MODULE = "Onlyoffice文件操作接口";
@Resource
IUserService userService;
@Resource
UFOFactory ufoFactory;
@Value("${deployment.host}")
private String deploymentHost;
@Resource
IFileService fileService;
@Resource
IUserFileService userFileService;
@ResponseBody
@RequestMapping(value = "/createofficefile", method = RequestMethod.POST)
public RestResult<Object> createOfficeFile(HttpServletRequest request, @RequestBody CreateOfficeFileDTO createOfficeFileDTO, @RequestHeader("token") String token) {
RestResult<Object> result = new RestResult<>();
try{
UserBean loginUser = userService.getUserBeanByToken(token);
if (loginUser == null) {
throw new NotLoginException();
}
String fileName = createOfficeFileDTO.getFileName();
String filePath = createOfficeFileDTO.getFilePath();
String extendName = createOfficeFileDTO.getExtendName();
List<UserFile> userFiles = userFileService.selectSameUserFile(fileName, filePath, extendName, loginUser.getUserId());
if (userFiles != null && !userFiles.isEmpty()) {
return RestResult.fail().message("同名文件已存在");
}
String uuid = UUID.randomUUID().toString().replaceAll("-","");
SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
String fileSavePath = PathUtil.getStaticPath() + "/create/" + formater.format(new Date());
File fileSavePathFile = new File(fileSavePath);
if (!fileSavePathFile.exists()) {
fileSavePathFile.mkdirs();
}
String fileUrl = "/create/" + formater.format(new Date()) + "/" + uuid + "." + extendName;
File file = new File(fileSavePath + "/" + uuid + "." + extendName);
if(!file.exists()){
try {
if("docx".equals(extendName)){
//创建word文档
XWPFDocument document= new XWPFDocument();
//Write the Document in file system
FileOutputStream out = new FileOutputStream(file);
document.write(out);
out.close();
}else if("xlsx".equals(extendName)){
//创建excel表格
XSSFWorkbook workbook = new XSSFWorkbook();
//创建工作表
workbook.createSheet("Sheet1");
//Write the Document in file system
FileOutputStream out = new FileOutputStream(file);
workbook.write(out);
out.close();
}else if("pptx".equals(extendName)){
//创建pptx演示文稿
XMLSlideShow pptx = new XMLSlideShow();
//创建工作表
//Write the Document in file system
FileOutputStream out = new FileOutputStream(file);
pptx.write(out);
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
FileBean fileBean = new FileBean();
fileBean.setFileSize(Long.valueOf(0));
fileBean.setFileUrl(fileUrl);
fileBean.setStorageType(0);
fileBean.setPointCount(1);
fileBean.setIdentifier(uuid);
fileBean.setTimeStampName(uuid);
boolean saveFlag = fileService.save(fileBean);
UserFile userFile = new UserFile();
if(saveFlag) {
userFile.setUserId(loginUser.getUserId());
userFile.setFileName(fileName);
userFile.setFilePath(filePath);
userFile.setDeleteFlag(0);
userFile.setIsDir(0);
userFile.setExtendName(extendName);
userFile.setUploadTime(DateUtil.getCurrentTime());
userFile.setFileId(fileBean.getFileId());
userFileService.save(userFile);
}
Long newFileSize = file.length();
//更新文件修改信息
LambdaUpdateWrapper<FileBean> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
FileInputStream fins = new FileInputStream(fileSavePath);
String md5Str = DigestUtils.md5Hex(fins);
fins.close();
lambdaUpdateWrapper
.set(FileBean::getIdentifier, md5Str)
.set(FileBean::getTimeStampName, md5Str)
.set(FileBean::getFileSize, newFileSize)
.eq(FileBean::getFileId, fileBean.getFileId());
fileService.update(lambdaUpdateWrapper);
result.success();
result.setMessage("文件创建成功!");
} catch (Exception e) {
log.error(e.getMessage());
result.setCode(500);
result.setMessage("服务器错误!");
}
return result;
}
@Operation(summary = "预览office文件", description = "预览office文件", tags = {"office"})
@MyLog(operation = "查看报告接口", module = CURRENT_MODULE)
@RequestMapping(value = "/previewofficefile", method = RequestMethod.POST)
@ResponseBody
public RestResult<Object> previewOfficeFile(HttpServletRequest request, @RequestBody PreviewOfficeFileDTO previewOfficeFileDTO, @RequestHeader("token") String token) {
RestResult<Object> result = new RestResult<>();
try {
UserBean loginUser = userService.getUserBeanByToken(token);
if (loginUser == null) {
throw new NotLoginException();
}
UserFile userFile = userFileService.getById(previewOfficeFileDTO.getUserFileId());
String baseUrl = request.getScheme()+"://"+ deploymentHost + request.getContextPath();
FileModel file = new FileModel(userFile.getFileName() + "." + userFile.getExtendName(),
previewOfficeFileDTO.getPreviewUrl(),
String.valueOf(new Date().getTime()),
String.valueOf(loginUser.getUserId()),
loginUser.getUsername(),
"view");
String query = "?type=show&token="+token;
file.editorConfig.callbackUrl= baseUrl + "/office/IndexServlet" + query;
JSONObject jsonObject = new JSONObject();
jsonObject.put("file",file);
jsonObject.put("docserviceApiUrl", ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.api"));
jsonObject.put("reportName",userFile.getFileName());
result.setData(jsonObject);
result.setCode(200);
result.setMessage("获取报告成功!");
} catch (Exception e) {
log.error(e.getMessage());
result.setCode(500);
result.setMessage("服务器错误!");
}
return result;
}
@ResponseBody
@RequestMapping(value = "/editofficefile", method = RequestMethod.POST)
public RestResult<Object> editOfficeFile(HttpServletRequest request, @RequestBody EditOfficeFileDTO editOfficeFileDTO, @RequestHeader("token") String token) {
RestResult<Object> result = new RestResult<>();
log.info("editOfficeFile");
try {
UserBean loginUser = userService.getUserBeanByToken(token);
if (loginUser == null) {
throw new NotLoginException();
}
UserFile userFile = userFileService.getById(editOfficeFileDTO.getUserFileId());
String baseUrl = request.getScheme()+"://"+ deploymentHost + request.getContextPath();
log.info("回调地址baseUrl" + baseUrl);
FileModel file = new FileModel(userFile.getFileName() + "." + userFile.getExtendName(),
editOfficeFileDTO.getPreviewUrl(),
String.valueOf(new Date().getTime()),
String.valueOf(loginUser.getUserId()),
loginUser.getUsername(),
"edit");
file.changeType(request.getParameter("mode"), "edit");
String query = "?type=edit&fileId="+userFile.getFileId()+"&token="+token;
file.editorConfig.callbackUrl= baseUrl + "/office/IndexServlet" + query;
JSONObject jsonObject = new JSONObject();
jsonObject.put("file",file);
jsonObject.put("docserviceApiUrl",ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.api"));
jsonObject.put("reportName",userFile.getFileName());
result.setData(jsonObject);
result.setCode(200);
result.setMessage("编辑报告成功!");
} catch (Exception e) {
log.error(e.getMessage());
result.setCode(500);
result.setMessage("服务器错误!");
}
return result;
}
@RequestMapping(value = "/IndexServlet", method = RequestMethod.POST)
@ResponseBody
public void IndexServlet(HttpServletResponse response, HttpServletRequest request) throws IOException {
String token = request.getParameter("token");
UserBean loginUser = userService.getUserBeanByToken(token);
if (loginUser == null) {
throw new NotLoginException();
}
PrintWriter writer = null;
JSONObject jsonObj=null;
try {
writer = response.getWriter();
Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");
String body = scanner.hasNext() ? scanner.next() : "";
jsonObj = JSON.parseObject(body);
log.debug("===saveeditedfile:" + jsonObj.get("status")) ;
String status = jsonObj!=null?jsonObj.get("status").toString():"";
if ("2".equals(status)) {//新建报告不强制手动操作时状态为2
String type = request.getParameter("type");
String downloadUri = (String) jsonObj.get("url");
if("edit".equals(type)){//修改报告
log.debug("====文档编辑完成,现在开始保存编辑后的文档,其下载地址为:" + downloadUri);
String fileId = request.getParameter("fileId");
String userFileId = request.getParameter("userFileId");
FileBean fileBean = fileService.getById(fileId);
if (fileBean.getPointCount() > 1) {
//该场景暂不支持编辑修改
writer.write("{\"error\":1}");
return ;
}
URL url = new URL(downloadUri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream stream = connection.getInputStream();
Writer writer1 = ufoFactory.getWriter(fileBean.getStorageType());
WriteFile writeFile = new WriteFile();
writeFile.setFileUrl(fileBean.getFileUrl());
int fileLength = connection.getContentLength();
log.info("当前修改文件大小为:" + fileLength);
writeFile.setFileSize(connection.getContentLength());
writer1.write(stream, writeFile);
//更新文件修改信息
LambdaUpdateWrapper<UserFile> userFileUpdateWrapper = new LambdaUpdateWrapper<>();
userFileUpdateWrapper
.set(UserFile::getUploadTime, DateUtil.getCurrentTime())
.eq(UserFile::getUserFileId, userFileId);
userFileService.update(userFileUpdateWrapper);
LambdaUpdateWrapper<FileBean> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
String md5Str = DigestUtils.md5Hex(stream);
log.info("当前修改文件大小为2222" + Long.valueOf(fileLength));
lambdaUpdateWrapper
.set(FileBean::getIdentifier, md5Str)
.set(FileBean::getFileSize, Long.valueOf(fileLength))
.eq(FileBean::getFileId, fileId);
fileService.update(lambdaUpdateWrapper);
connection.disconnect();
}
}
}catch (Exception e) {
log.error(e.getMessage());
}
String status = jsonObj!=null?jsonObj.get("status").toString():"";
if("3".equals(status)||"7".equals(status)) {//不强制手动保存时为6,"6".equals(status)
log.debug("====保存失败:");
writer.write("{\"error\":1}");
}else {
log.debug("状态为0") ;
writer.write("{\"error\":" + "0" + "}");
}
}
}

View File

@ -0,0 +1,315 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.domain;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.qiwenshare.file.helper.DocumentManager;
import com.qiwenshare.file.helper.FileUtility;
import com.qiwenshare.file.helper.ServiceConverter;
import lombok.Data;
import java.io.File;
import java.io.FileInputStream;
import java.util.*;
@Data
public class FileModel
{
public String type = "desktop";
public String mode = "edit";
public String documentType;
public Document document;
public EditorConfig editorConfig;
public String token;
public FileModel(String fileName, String fileUrl, String fileModifyTime, String uid, String uname, String mode)
{
if (fileName == null) fileName = "";
fileName = fileName.trim();
documentType = FileUtility.GetFileType(fileName).toString().toLowerCase();
document = new Document();
document.title = fileName;
document.url = fileUrl;
// document.urlUser = DocumentManager.GetFileUri(fileName, false);
document.fileType = FileUtility.GetFileExtension(fileName).replace(".", "");
document.key = ServiceConverter.GenerateRevisionId(DocumentManager.CurUserHostAddress(null) + "/" + fileName + "/" + fileModifyTime);
document.info = new Info();
document.info.favorite = uid != null && !uid.isEmpty() ? uid.equals("uid-2") : null;
editorConfig = new EditorConfig(null);
// editorConfig.callbackUrl = DocumentManager.GetCallback(fileName);
// editorConfig.lang = null;
if (uid != null) editorConfig.user.id = uid;
if (uname != null) editorConfig.user.name = uid.equals("uid-0") ? null : uname;
if (editorConfig.user.id.equals("uid-2")) editorConfig.user.group = "group-2";
if (editorConfig.user.id.equals("uid-3")) editorConfig.user.group = "group-3";
// editorConfig.customization.goback.url = DocumentManager.GetServerUrl(false) + "/IndexServlet";
changeType(mode, type);
}
public void changeType(String _mode, String _type)
{
if (_mode != null) mode = _mode;
if (_type != null) type = _type;
Boolean canEdit = DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(document.title));
editorConfig.customization.submitForm = canEdit && (mode.equals("edit") || mode.equals("fillForms"));
editorConfig.mode = canEdit && !mode.equals("view") ? "edit" : "view";
document.permissions = new Permissions(mode, type, canEdit);
if (type.equals("embedded")) InitDesktop();
}
public void InitDesktop()
{
editorConfig.InitDesktop(document.urlUser);
}
public void BuildToken()
{
Map<String, Object> map = new HashMap<>();
map.put("type", type);
map.put("documentType", documentType);
map.put("document", document);
map.put("editorConfig", editorConfig);
token = DocumentManager.CreateToken(map);
}
public String[] GetHistory()
{
String histDir = DocumentManager.HistoryDir(DocumentManager.StoragePath(document.title, null));
if (DocumentManager.GetFileVersion(histDir) > 0) {
Integer curVer = DocumentManager.GetFileVersion(histDir);
List<Object> hist = new ArrayList<>();
Map<String, Object> histData = new HashMap<String, Object>();
for (Integer i = 1; i <= curVer; i++) {
Map<String, Object> obj = new HashMap<String, Object>();
Map<String, Object> dataObj = new HashMap<String, Object>();
String verDir = DocumentManager.VersionDir(histDir, i);
try {
String key = null;
key = i == curVer ? document.key : readFileToEnd(new File(verDir + File.separator + "key.txt"));
obj.put("key", key);
obj.put("version", i);
if (i == 1) {
String createdInfo = readFileToEnd(new File(histDir + File.separator + "createdInfo.json"));
JSONObject json = JSONObject.parseObject(createdInfo);
obj.put("created", json.get("created"));
Map<String, Object> user = new HashMap<String, Object>();
user.put("id", json.get("id"));
user.put("name", json.get("name"));
obj.put("user", user);
}
dataObj.put("key", key);
dataObj.put("url", i == curVer ? document.url : DocumentManager.GetPathUri(verDir + File.separator + "prev" + FileUtility.GetFileExtension(document.title)));
dataObj.put("version", i);
if (i > 1) {
JSONObject changes = JSONObject.parseObject(readFileToEnd(new File(DocumentManager.VersionDir(histDir, i - 1) + File.separator + "changes.json")));
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
obj.put("changes", changes.get("changes"));
obj.put("serverVersion", changes.get("serverVersion"));
obj.put("created", change.get("created"));
obj.put("user", change.get("user"));
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 2));
Map<String, Object> prevInfo = new HashMap<String, Object>();
prevInfo.put("key", prev.get("key"));
prevInfo.put("url", prev.get("url"));
dataObj.put("previous", prevInfo);
dataObj.put("changesUrl", DocumentManager.GetPathUri(DocumentManager.VersionDir(histDir, i - 1) + File.separator + "diff.zip"));
}
if (DocumentManager.TokenEnabled())
{
dataObj.put("token", DocumentManager.CreateToken(dataObj));
}
hist.add(obj);
histData.put(Integer.toString(i - 1), dataObj);
} catch (Exception ex) { }
}
Map<String, Object> histObj = new HashMap<String, Object>();
histObj.put("currentVersion", curVer);
histObj.put("history", hist);
Gson gson = new Gson();
return new String[] { gson.toJson(histObj), gson.toJson(histData) };
}
return new String[] { "", "" };
}
private String readFileToEnd(File file) {
String output = "";
try {
try(FileInputStream is = new FileInputStream(file))
{
Scanner scanner = new Scanner(is);
scanner.useDelimiter("\\A");
while (scanner.hasNext()) {
output += scanner.next();
}
scanner.close();
}
} catch (Exception e) { }
return output;
}
@Data
public class Document
{
public String title;
public String url;
public String urlUser;
public String fileType;
public String key;
public Info info;
public Permissions permissions;
}
@Data
public class Permissions
{
public Boolean comment;
public Boolean download;
public Boolean edit;
public Boolean fillForms;
public Boolean modifyFilter;
public Boolean modifyContentControl;
public Boolean review;
public List<String> reviewGroups;
public Permissions(String mode, String type, Boolean canEdit)
{
comment = !mode.equals("view") && !mode.equals("fillForms") && !mode.equals("embedded") && !mode.equals("blockcontent");
download = true;
edit = canEdit && (mode.equals("edit") || mode.equals("view") || mode.equals("filter") || mode.equals("blockcontent"));
fillForms = !mode.equals("view") && !mode.equals("comment") && !mode.equals("embedded") && !mode.equals("blockcontent");
modifyFilter = !mode.equals("filter");
modifyContentControl = !mode.equals("blockcontent");
review = mode.equals("edit") || mode.equals("review");
reviewGroups = editorConfig.user.group != null ? GetReviewGroups(editorConfig.user.group) : null;
}
private List<String> GetReviewGroups(String group){
Map<String, List<String>> reviewGroups = new HashMap<>();
reviewGroups.put("group-2", Arrays.asList("group-2", ""));
reviewGroups.put("group-3", Arrays.asList("group-2"));
return reviewGroups.get(group);
}
}
@Data
public class Info
{
Boolean favorite;
}
public class EditorConfig
{
public HashMap<String, Object> actionLink = null;
public String mode = "edit";
public String callbackUrl;
public String lang = "en";
public User user;
public Customization customization;
public Embedded embedded;
public EditorConfig(String actionData)
{
if (actionData != null) {
Gson gson = new Gson();
actionLink = gson.fromJson(actionData, new TypeToken<HashMap<String, Object>>() { }.getType());
}
user = new User();
customization = new Customization();
}
public void InitDesktop(String url)
{
embedded = new Embedded();
embedded.saveUrl = url;
embedded.embedUrl = url;
embedded.shareUrl = url;
embedded.toolbarDocked = "top";
}
public class User
{
public String id = "uid-1";
public String name = "John Smith";
public String group = null;
}
public class Customization
{
public Goback goback;
public Boolean forcesave;
public Boolean submitForm;
public Customization()
{
forcesave = false;
goback = new Goback();
}
public class Goback
{
public String url;
}
}
public class Embedded
{
public String saveUrl;
public String embedUrl;
public String shareUrl;
public String toolbarDocked;
}
}
public static String Serialize(FileModel model)
{
Gson gson = new Gson();
return gson.toJson(model);
}
}

View File

@ -0,0 +1,26 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.domain;
public enum FileType
{
Word,
Cell,
Slide
}

View File

@ -0,0 +1,10 @@
package com.qiwenshare.file.dto.file;
import lombok.Data;
@Data
public class CreateOfficeFileDTO {
private String filePath;
private String fileName;
private String extendName;
}

View File

@ -0,0 +1,12 @@
package com.qiwenshare.file.dto.file;
import lombok.Data;
@Data
public class EditOfficeFileDTO {
private long userFileId;
private String previewUrl;
// private String filePath;
// private String fileName;
// private String extendName;
}

View File

@ -0,0 +1,15 @@
package com.qiwenshare.file.dto.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class OnlyofficeDTO {
private long fileId;
private String fileName;
private String fileUrl;
private String extendName;
}

View File

@ -0,0 +1,12 @@
package com.qiwenshare.file.dto.file;
import lombok.Data;
@Data
public class PreviewOfficeFileDTO {
private long userFileId;
private String previewUrl;
// private String filePath;
// private String fileName;
// private String extendName;
}

View File

@ -0,0 +1,61 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.helper;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.Properties;
@Component
public class ConfigManager
{
private static Properties properties;
static
{
Init();
}
private static void Init()
{
try
{
properties = new Properties();
InputStream stream = ConfigManager.class.getResourceAsStream("/config/settings.properties");
// InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("settings.properties");
properties.load(stream);
}
catch (Exception ex)
{
properties = null;
}
}
public static String GetProperty(String name)
{
if (properties == null)
{
return "";
}
String property = properties.getProperty(name);
return property == null ? "" : property;
}
}

View File

@ -0,0 +1,414 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.helper;
import com.alibaba.fastjson.JSONObject;
import com.qiwenshare.file.domain.FileType;
import org.primeframework.jwt.Signer;
import org.primeframework.jwt.Verifier;
import org.primeframework.jwt.domain.JWT;
import org.primeframework.jwt.hmac.HMACSigner;
import org.primeframework.jwt.hmac.HMACVerifier;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
public class DocumentManager
{
private static HttpServletRequest request;
public static void Init(HttpServletRequest req, HttpServletResponse resp)
{
request = req;
}
public static long GetMaxFileSize()
{
long size;
try
{
size = Long.parseLong(ConfigManager.GetProperty("filesize-max"));
}
catch (Exception ex)
{
size = 0;
}
return size > 0 ? size : 5 * 1024 * 1024;
}
public static List<String> GetFileExts()
{
List<String> res = new ArrayList<>();
res.addAll(GetViewedExts());
res.addAll(GetEditedExts());
res.addAll(GetConvertExts());
return res;
}
public static List<String> GetViewedExts()
{
String exts = ConfigManager.GetProperty("files.docservice.viewed-docs");
return Arrays.asList(exts.split("\\|"));
}
public static List<String> GetEditedExts()
{
String exts = ConfigManager.GetProperty("files.docservice.edited-docs");
return Arrays.asList(exts.split("\\|"));
}
public static List<String> GetConvertExts()
{
String exts = ConfigManager.GetProperty("files.docservice.convert-docs");
return Arrays.asList(exts.split("\\|"));
}
public static String CurUserHostAddress(String userAddress)
{
if(userAddress == null)
{
try
{
userAddress = InetAddress.getLocalHost().getHostAddress();
}
catch (Exception ex)
{
userAddress = "";
}
}
return userAddress.replaceAll("[^0-9a-zA-Z.=]", "_");
}
public static String FilesRootPath(String userAddress)
{
String hostAddress = CurUserHostAddress(userAddress);
String serverPath = request.getSession().getServletContext().getRealPath("");
String storagePath = ConfigManager.GetProperty("storage-folder");
String directory = serverPath + storagePath + File.separator + hostAddress + File.separator;
File file = new File(directory);
if (!file.exists())
{
file.mkdirs();
}
return directory;
}
public static String StoragePath(String fileName, String userAddress)
{
String directory = FilesRootPath(userAddress);
return directory + FileUtility.GetFileName(fileName);
}
public static String ForcesavePath(String fileName, String userAddress, Boolean create)
{
String hostAddress = CurUserHostAddress(userAddress);
String serverPath = request.getSession().getServletContext().getRealPath("");
String storagePath = ConfigManager.GetProperty("storage-folder");
String directory = serverPath + storagePath + File.separator + hostAddress + File.separator;
File file = new File(directory);
if (!file.exists()) return "";
directory = directory + fileName + "-hist" + File.separator;
file = new File(directory);
if (!create && !file.exists()) return "";
file.mkdirs();
directory = directory + fileName;
file = new File(directory);
if (!create && !file.exists()) {
return "";
}
return directory;
}
public static String HistoryDir(String storagePath)
{
return storagePath += "-hist";
}
public static String VersionDir(String histPath, Integer version)
{
return histPath + File.separator + Integer.toString(version);
}
public static String VersionDir(String fileName, String userAddress, Integer version)
{
return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version);
}
public static Integer GetFileVersion(String historyPath)
{
File dir = new File(historyPath);
if (!dir.exists()) return 0;
File[] dirs = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
return dirs.length + 1;
}
public static int GetFileVersion(String fileName, String userAddress)
{
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
}
public static String GetCorrectName(String fileName, String userAddress)
{
String baseName = FileUtility.GetFileNameWithoutExtension(fileName);
String ext = FileUtility.GetFileExtension(fileName);
String name = baseName + ext;
File file = new File(StoragePath(name, userAddress));
for (int i = 1; file.exists(); i++)
{
name = baseName + " (" + i + ")" + ext;
file = new File(StoragePath(name, userAddress));
}
return name;
}
public static void CreateMeta(String fileName, String uid, String uname, String userAddress) throws Exception
{
String histDir = HistoryDir(StoragePath(fileName, userAddress));
File dir = new File(histDir);
dir.mkdir();
JSONObject json = new JSONObject();
json.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
json.put("id", (uid == null || uid.isEmpty()) ? "uid-1" : uid);
if (json.get("id").equals("uid-0")) {
json.put("name", null);
} else {
json.put("name", (uname == null || uname.isEmpty()) ? "John Smith" : uname);
}
File meta = new File(histDir + File.separator + "createdInfo.json");
try (FileWriter writer = new FileWriter(meta)) {
json.writeJSONString(writer);
}
}
public static File[] GetStoredFiles(String userAddress)
{
String directory = FilesRootPath(userAddress);
File file = new File(directory);
return file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isFile();
}
});
}
public static String CreateDemo(String fileExt, Boolean sample, String uid, String uname) throws Exception
{
String demoName = (sample ? "sample." : "new.") + fileExt;
String demoPath = "assets" + File.separator + (sample ? "sample" : "new") + File.separator;
String fileName = GetCorrectName(demoName, null);
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(demoPath + demoName);
File file = new File(StoragePath(fileName, null));
try (FileOutputStream out = new FileOutputStream(file))
{
int read;
final byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1)
{
out.write(bytes, 0, read);
}
out.flush();
}
CreateMeta(fileName, uid, uname, null);
return fileName;
}
public static String GetFileUri(String fileName, Boolean forDocumentServer)
{
try
{
String serverPath = GetServerUrl(forDocumentServer);
String storagePath = ConfigManager.GetProperty("storage-folder");
String hostAddress = CurUserHostAddress(null);
String filePath = serverPath + "/" + storagePath + "/" + hostAddress + "/" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()).replace("+", "%20");
return filePath;
}
catch (UnsupportedEncodingException e)
{
return "";
}
}
public static ArrayList<Map<String, Object>> GetFilesInfo(){
ArrayList<Map<String, Object>> files = new ArrayList<>();
for(File file : GetStoredFiles(null)){
Map<String, Object> map = new LinkedHashMap<>();
map.put("version", GetFileVersion(file.getName(), null));
map.put("id", ServiceConverter.GenerateRevisionId(CurUserHostAddress(null) + "/" + file.getName() + "/" + Long.toString(new File(StoragePath(file.getName(), null)).lastModified())));
map.put("contentLength", new BigDecimal(String.valueOf((file.length()/1024.0))).setScale(2, RoundingMode.HALF_UP) + " KB");
map.put("pureContentLength", file.length());
map.put("title", file.getName());
map.put("updated", String.valueOf(new Date(file.lastModified())));
files.add(map);
}
return files;
}
public static ArrayList<Map<String, Object>> GetFilesInfo(String fileId){
ArrayList<Map<String, Object>> file = new ArrayList<>();
for (Map<String, Object> map : GetFilesInfo()){
if (map.get("id").equals(fileId)){
file.add(map);
break;
}
}
return file;
}
public static String GetPathUri(String path)
{
String serverPath = GetServerUrl(true);
String storagePath = ConfigManager.GetProperty("storage-folder");
String hostAddress = CurUserHostAddress(null);
String filePath = serverPath + "/" + storagePath + "/" + hostAddress + "/" + path.replace(File.separator, "/").substring(FilesRootPath(null).length()).replace(" ", "%20");
return filePath;
}
public static String GetServerUrl(Boolean forDocumentServer) {
if (forDocumentServer && !ConfigManager.GetProperty("files.docservice.url.example").equals("")) {
return ConfigManager.GetProperty("files.docservice.url.example");
} else {
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
}
}
public static String GetCallback(String fileName)
{
String serverPath = GetServerUrl(true);
String hostAddress = CurUserHostAddress(null);
try
{
String query = "?type=track&fileName=" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()) + "&userAddress=" + URLEncoder.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString());
return serverPath + "/IndexServlet" + query;
}
catch (UnsupportedEncodingException e)
{
return "";
}
}
public static String GetInternalExtension(FileType fileType)
{
if (fileType.equals(FileType.Word))
return ".docx";
if (fileType.equals(FileType.Cell))
return ".xlsx";
if (fileType.equals(FileType.Slide))
return ".pptx";
return ".docx";
}
public static String CreateToken(Map<String, Object> payloadClaims)
{
try
{
Signer signer = HMACSigner.newSHA256Signer(GetTokenSecret());
JWT jwt = new JWT();
for (String key : payloadClaims.keySet())
{
jwt.addClaim(key, payloadClaims.get(key));
}
return JWT.getEncoder().encode(jwt, signer);
}
catch (Exception e)
{
return "";
}
}
public static JWT ReadToken(String token)
{
try
{
Verifier verifier = HMACVerifier.newVerifier(GetTokenSecret());
return JWT.getDecoder().decode(token, verifier);
}
catch (Exception exception)
{
return null;
}
}
public static Boolean TokenEnabled()
{
String secret = GetTokenSecret();
return secret != null && !secret.isEmpty();
}
private static String GetTokenSecret()
{
return ConfigManager.GetProperty("files.docservice.secret");
}
}

View File

@ -0,0 +1,121 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.helper;
import com.qiwenshare.file.domain.FileType;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FileUtility
{
static {}
public static FileType GetFileType(String fileName)
{
String ext = GetFileExtension(fileName).toLowerCase();
if (ExtsDocument.contains(ext))
return FileType.Word;
if (ExtsSpreadsheet.contains(ext))
return FileType.Cell;
if (ExtsPresentation.contains(ext))
return FileType.Slide;
return FileType.Word;
}
public static List<String> ExtsDocument = Arrays.asList
(
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps"
);
public static List<String> ExtsSpreadsheet = Arrays.asList
(
".xls", ".xlsx", ".xlsm",
".xlt", ".xltx", ".xltm",
".ods", ".fods", ".ots", ".csv"
);
public static List<String> ExtsPresentation = Arrays.asList
(
".pps", ".ppsx", ".ppsm",
".ppt", ".pptx", ".pptm",
".pot", ".potx", ".potm",
".odp", ".fodp", ".otp"
);
public static String GetFileName(String url)
{
if (url == null) return "";
String fileName = url.substring(url.lastIndexOf('/') + 1, url.length());
fileName = fileName.split("\\?")[0];
return fileName;
}
public static String GetFileNameWithoutExtension(String url)
{
String fileName = GetFileName(url);
if (fileName == null) return null;
String fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.'));
return fileNameWithoutExt;
}
public static String GetFileExtension(String url)
{
String fileName = GetFileName(url);
if (fileName == null) return null;
String fileExt = fileName.substring(fileName.lastIndexOf("."));
return fileExt.toLowerCase();
}
public static Map<String, String> GetUrlParams(String url)
{
try
{
String query = new URL(url).getQuery();
String[] params = query.split("&");
Map<String, String> map = new HashMap<>();
for (String param : params)
{
String name = param.split("=")[0];
String value = param.split("=")[1];
map.put(name, value);
}
return map;
}
catch (Exception ex)
{
return null;
}
}
}

View File

@ -0,0 +1,242 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.helper;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class ServiceConverter
{
private static int ConvertTimeout = 120000;
private static final String DocumentConverterUrl = ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.converter");
private static final String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header");
public static class ConvertBody
{
public String url;
public String outputtype;
public String filetype;
public String title;
public String key;
public Boolean async;
public String token;
public String password;
}
static
{
try
{
int timeout = Integer.parseInt(ConfigManager.GetProperty("files.docservice.timeout"));
if (timeout > 0)
{
ConvertTimeout = timeout;
}
}
catch (Exception ex)
{
}
}
public static String GetConvertedUri(String documentUri, String fromExtension, String toExtension, String documentRevisionId, String filePass, Boolean isAsync) throws Exception
{
fromExtension = fromExtension == null || fromExtension.isEmpty() ? FileUtility.GetFileExtension(documentUri) : fromExtension;
String title = FileUtility.GetFileName(documentUri);
title = title == null || title.isEmpty() ? UUID.randomUUID().toString() : title;
documentRevisionId = documentRevisionId == null || documentRevisionId.isEmpty() ? documentUri : documentRevisionId;
documentRevisionId = GenerateRevisionId(documentRevisionId);
ConvertBody body = new ConvertBody();
body.url = documentUri;
body.outputtype = toExtension.replace(".", "");
body.filetype = fromExtension.replace(".", "");
body.title = title;
body.key = documentRevisionId;
body.password = filePass;
if (isAsync)
body.async = true;
String headerToken = "";
if (DocumentManager.TokenEnabled())
{
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("url", body.url);
map.put("outputtype", body.outputtype);
map.put("filetype", body.filetype);
map.put("title", body.title);
map.put("key", body.key);
map.put("password", body.password);
if (isAsync)
map.put("async", body.async);
String token = DocumentManager.CreateToken(map);
body.token = token;
Map<String, Object> payloadMap = new HashMap<String, Object>();
payloadMap.put("payload", map);
headerToken = DocumentManager.CreateToken(payloadMap);
}
Gson gson = new Gson();
String bodyString = gson.toJson(body);
byte[] bodyByte = bodyString.getBytes(StandardCharsets.UTF_8);
URL url = new URL(DocumentConverterUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setFixedLengthStreamingMode(bodyByte.length);
connection.setRequestProperty("Accept", "application/json");
connection.setConnectTimeout(ConvertTimeout);
if (DocumentManager.TokenEnabled())
{
connection.setRequestProperty(DocumentJwtHeader.equals("") ? "Authorization" : DocumentJwtHeader, "Bearer " + headerToken);
}
connection.connect();
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte);
}
InputStream stream = connection.getInputStream();
if (stream == null)
throw new Exception("Could not get an answer");
String jsonString = ConvertStreamToString(stream);
connection.disconnect();
return GetResponseUri(jsonString);
}
public static String GenerateRevisionId(String expectedKey)
{
if (expectedKey.length() > 20)
expectedKey = Integer.toString(expectedKey.hashCode());
String key = expectedKey.replace("[^0-9-.a-zA-Z_=]", "_");
return key.substring(0, Math.min(key.length(), 20));
}
private static void ProcessConvertServiceResponceError(int errorCode) throws Exception
{
String errorMessage = "";
String errorMessageTemplate = "Error occurred in the ConvertService: ";
switch (errorCode)
{
case -8:
errorMessage = errorMessageTemplate + "Error document VKey";
break;
case -7:
errorMessage = errorMessageTemplate + "Error document request";
break;
case -6:
errorMessage = errorMessageTemplate + "Error database";
break;
case -5:
errorMessage = errorMessageTemplate + "Incorrect password";
break;
case -4:
errorMessage = errorMessageTemplate + "Error download error";
break;
case -3:
errorMessage = errorMessageTemplate + "Error convertation error";
break;
case -2:
errorMessage = errorMessageTemplate + "Error convertation timeout";
break;
case -1:
errorMessage = errorMessageTemplate + "Error convertation unknown";
break;
case 0:
break;
default:
errorMessage = "ErrorCode = " + errorCode;
break;
}
throw new Exception(errorMessage);
}
private static String GetResponseUri(String jsonString) throws Exception
{
JSONObject jsonObj = ConvertStringToJSON(jsonString);
Object error = jsonObj.get("error");
if (error != null)
ProcessConvertServiceResponceError(Math.toIntExact((long)error));
Boolean isEndConvert = (Boolean) jsonObj.get("endConvert");
Long resultPercent = 0l;
String responseUri = null;
if (isEndConvert)
{
resultPercent = 100l;
responseUri = (String) jsonObj.get("fileUrl");
}
else
{
resultPercent = (Long) jsonObj.get("percent");
resultPercent = resultPercent >= 100l ? 99l : resultPercent;
}
return resultPercent >= 100l ? responseUri : "";
}
public static String ConvertStreamToString(InputStream stream) throws IOException
{
InputStreamReader inputStreamReader = new InputStreamReader(stream);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = bufferedReader.readLine();
while (line != null)
{
stringBuilder.append(line);
line = bufferedReader.readLine();
}
String result = stringBuilder.toString();
return result;
}
public static JSONObject ConvertStringToJSON(String jsonString)
{
return JSONObject.parseObject(jsonString);
}
}

View File

@ -0,0 +1,301 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.qiwenshare.file.helper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import org.primeframework.jwt.domain.JWT;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class TrackManager {
private static final String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header");
public static JSONObject readBody(HttpServletRequest request, PrintWriter writer) throws Exception {
String bodyString = "";
try {
Scanner scanner = new Scanner(request.getInputStream());
scanner.useDelimiter("\\A");
bodyString = scanner.hasNext() ? scanner.next() : "";
scanner.close();
}
catch (Exception ex) {
writer.write("get request.getInputStream error:" + ex.getMessage());
throw ex;
}
if (bodyString.isEmpty()) {
writer.write("empty request.getInputStream");
throw new Exception("empty request.getInputStream");
}
JSONObject body;
try {
body = JSONObject.parseObject(bodyString);
} catch (Exception ex) {
writer.write("JSONParser.parse error:" + ex.getMessage());
throw ex;
}
if (DocumentManager.TokenEnabled()) {
String token = (String) body.get("token");
if (token == null) {
String header = (String) request.getHeader(DocumentJwtHeader == null || DocumentJwtHeader.isEmpty() ? "Authorization" : DocumentJwtHeader);
if (header != null && !header.isEmpty()) {
token = header.startsWith("Bearer ") ? header.substring(7) : header;
}
}
if (token == null || token.isEmpty()) {
writer.write("{\"error\":1,\"message\":\"JWT expected\"}");
throw new Exception("{\"error\":1,\"message\":\"JWT expected\"}");
}
JWT jwt = DocumentManager.ReadToken(token);
if (jwt == null) {
writer.write("{\"error\":1,\"message\":\"JWT validation failed\"}");
throw new Exception("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
if (jwt.getObject("payload") != null) {
try {
@SuppressWarnings("unchecked") LinkedHashMap<String, Object> payload =
(LinkedHashMap<String, Object>)jwt.getObject("payload");
jwt.claims = payload;
} catch (Exception ex) {
writer.write("{\"error\":1,\"message\":\"Wrong payload\"}");
throw ex;
}
}
try {
Gson gson = new Gson();
body = JSONObject.parseObject(gson.toJson(jwt.claims));
} catch (Exception ex) {
writer.write("JSONParser.parse error:" + ex.getMessage());
throw ex;
}
}
return body;
}
public static void processSave(JSONObject body, String fileName, String userAddress) throws Exception {
String downloadUri = (String) body.get("url");
String changesUri = (String) body.get("changesurl");
String key = (String) body.get("key");
String newFileName = fileName;
String curExt = FileUtility.GetFileExtension(fileName);
String downloadExt = FileUtility.GetFileExtension(downloadUri);
if (!curExt.equals(downloadExt)) {
try {
String newFileUri = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), null, false);
if (newFileUri.isEmpty()) {
newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
} else {
downloadUri = newFileUri;
}
} catch (Exception e){
newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
String storagePath = DocumentManager.StoragePath(newFileName, userAddress);
File histDir = new File(DocumentManager.HistoryDir(storagePath));
if (!histDir.exists()) histDir.mkdirs();
String versionDir = DocumentManager.VersionDir(histDir.getAbsolutePath(), DocumentManager.GetFileVersion(histDir.getAbsolutePath()));
File ver = new File(versionDir);
File lastVersion = new File(DocumentManager.StoragePath(fileName, userAddress));
File toSave = new File(storagePath);
if (!ver.exists()) ver.mkdirs();
lastVersion.renameTo(new File(versionDir + File.separator + "prev" + curExt));
downloadToFile(downloadUri, toSave);
downloadToFile(changesUri, new File(versionDir + File.separator + "diff.zip"));
String history = (String) body.get("changeshistory");
if (history == null && body.containsKey("history")) {
history = ((JSONObject) body.get("history")).toJSONString();
}
if (history != null && !history.isEmpty()) {
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "changes.json"));
fw.write(history);
fw.close();
}
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "key.txt"));
fw.write(key);
fw.close();
String forcesavePath = DocumentManager.ForcesavePath(newFileName, userAddress, false);
if (!forcesavePath.equals("")) {
File forceSaveFile = new File(forcesavePath);
forceSaveFile.delete();
}
}
public static void processForceSave(JSONObject body, String fileName, String userAddress) throws Exception {
String downloadUri = (String) body.get("url");
String curExt = FileUtility.GetFileExtension(fileName);
String downloadExt = FileUtility.GetFileExtension(downloadUri);
Boolean newFileName = false;
if (!curExt.equals(downloadExt)) {
try {
String newFileUri = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), null, false);
if (newFileUri.isEmpty()) {
newFileName = true;
} else {
downloadUri = newFileUri;
}
} catch (Exception e){
newFileName = true;
}
}
String forcesavePath = "";
boolean isSubmitForm = body.get("forcesavetype").toString().equals("3");
if (isSubmitForm) {
//new file
if (newFileName){
fileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + "-form" + downloadExt, userAddress);
} else {
fileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + "-form" + curExt, userAddress);
}
forcesavePath = DocumentManager.StoragePath(fileName, userAddress);
} else {
if (newFileName){
fileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
forcesavePath = DocumentManager.ForcesavePath(fileName, userAddress, false);
if (forcesavePath == "") {
forcesavePath = DocumentManager.ForcesavePath(fileName, userAddress, true);
}
}
File toSave = new File(forcesavePath);
downloadToFile(downloadUri, toSave);
if (isSubmitForm) {
JSONArray actions = (JSONArray) body.get("actions");
JSONObject action = (JSONObject) actions.get(0);
String user = (String) action.get("userid");
DocumentManager.CreateMeta(fileName, user, "Filling Form", userAddress);
}
}
private static void downloadToFile(String url, File file) throws Exception {
if (url == null || url.isEmpty()) throw new Exception("argument url");
if (file == null) throw new Exception("argument path");
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
InputStream stream = connection.getInputStream();
if (stream == null)
{
throw new Exception("Stream is null");
}
try (FileOutputStream out = new FileOutputStream(file))
{
int read;
final byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1)
{
out.write(bytes, 0, read);
}
out.flush();
}
connection.disconnect();
}
public static void commandRequest(String method, String key) throws Exception {
String DocumentCommandUrl = ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.command");
URL url = new URL(DocumentCommandUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("c", method);
params.put("key", key);
String headerToken = "";
if (DocumentManager.TokenEnabled())
{
Map<String, Object> payloadMap = new HashMap<String, Object>();
payloadMap.put("payload", params);
headerToken = DocumentManager.CreateToken(payloadMap);
connection.setRequestProperty(DocumentJwtHeader.equals("") ? "Authorization" : DocumentJwtHeader, "Bearer " + headerToken);
String token = DocumentManager.CreateToken(params);
params.put("token", token);
}
Gson gson = new Gson();
String bodyString = gson.toJson(params);
byte[] bodyByte = bodyString.getBytes(StandardCharsets.UTF_8);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setDoOutput(true);
connection.connect();
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte);
}
InputStream stream = connection.getInputStream();;
if (stream == null)
throw new Exception("Could not get an answer");
String jsonString = ServiceConverter.ConvertStreamToString(stream);
connection.disconnect();
JSONObject response = ServiceConverter.ConvertStringToJSON(jsonString);
if (!response.get("error").toString().equals("0")){
throw new Exception(response.toJSONString());
}
}
}

View File

@ -12,7 +12,7 @@ import java.util.Map;
public interface UserFileMapper extends BaseMapper<UserFile> {
void replaceFilePath(@Param("filePath") String filePath, @Param("oldFilePath") String oldFilePath, @Param("userId") Long userId);
List<FileListVo> userFileList(UserFile userFile, Long beginCount, Long pageCount);
List<FileListVo> userFileList(@Param("userFile") UserFile userFile, Long beginCount, Long pageCount);
void updateFilepathByPathAndName(String oldfilePath, String newfilePath, String fileName, String extendName, long userId);
void updateFilepathByFilepath(String oldfilePath, String newfilePath, long userId);

View File

@ -47,6 +47,17 @@ public class UserFileService extends ServiceImpl<UserFileMapper, UserFile> impl
return userFileMapper.selectList(lambdaQueryWrapper);
}
@Override
public List<UserFile> selectSameUserFile(String fileName, String filePath, String extendName, Long userId) {
LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(UserFile::getFileName, fileName)
.eq(UserFile::getFilePath, filePath)
.eq(UserFile::getUserId, userId)
.eq(UserFile::getExtendName, extendName)
.eq(UserFile::getDeleteFlag, "0");
return userFileMapper.selectList(lambdaQueryWrapper);
}
@Override
public void replaceUserFilePath(String filePath, String oldFilePath, Long userId) {
userFileMapper.replaceFilePath(filePath, oldFilePath, userId);

View File

@ -93,3 +93,8 @@ spring.redis.timeout=5000
spring.data.elasticsearch.client.reactive.endpoints=127.0.0.1:9200
spring.elasticsearch.rest.uris=127.0.0.1:9200
# 当前部署外网IP用于office预览
deployment.host: 172.17.242.97:${server.port}

View File

@ -0,0 +1,18 @@
filesize-max=5242880
storage-folder=app_data
files.docservice.viewed-docs=.pdf|.djvu|.xps
files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2
files.docservice.timeout=120000
files.docservice.url.site=http://172.17.242.97:80/
files.docservice.url.converter=ConvertService.ashx
files.docservice.url.command=coauthoring/CommandService.ashx
files.docservice.url.api=web-apps/apps/api/documents/api.js
files.docservice.url.preloader=web-apps/apps/api/documents/cache-scripts.html
files.docservice.url.example=
#files.docservice.plugins=../../../../sdkjs-plugins/sdkjs-plugins-auto/textlibrary/config.json,../../../../sdkjs-plugins/sdkjs-plugins-auto/clipart/config.json
files.docservice.secret=
files.docservice.header=Authorization