Compare commits

...

9 Commits

Author SHA1 Message Date
  winter b46040c855 fix bug 4 years ago
  Stormeye Wu 09f323cc30 支持前缀 6 years ago
  jueyue 202aa3fe42 发布4.2.0版本 6 years ago
  jueyue 0ceb3ed0b4 !67 修复 SAX SheetHandler 特殊情境下导致列错位 6 years ago
  shuai.zhang01 42e8287156 fix SheetHandler 完善空单元格错位处理 6 years ago
  jueyue fad3c77070 访问路径加上前缀 6 years ago
  jueyue 69a337e3cd 中文编码 6 years ago
  jueyue f6e33e0768 easypoi-wps模块,支持excel的预览以及编辑 6 years ago
  jueyue 6318b414dd XLSX水印工具类 6 years ago
44 changed files with 1325 additions and 34 deletions
Split View
  1. +4
    -4
      README-cn.md
  2. +4
    -4
      README.md
  3. +1
    -1
      easypoi-annotation/pom.xml
  4. +5
    -0
      easypoi-annotation/src/main/java/cn/afterturn/easypoi/excel/annotation/Excel.java
  5. +6
    -2
      easypoi-base/pom.xml
  6. +4
    -0
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/entity/params/ExcelExportEntity.java
  7. +4
    -0
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/entity/params/ExcelImportEntity.java
  8. +4
    -0
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/export/base/ExportCommonService.java
  9. +1
    -1
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/export/template/ExcelExportOfTemplateUtil.java
  10. +7
    -7
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/html/helper/MergedRegionHelper.java
  11. +18
    -0
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/CellValueService.java
  12. +3
    -3
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/ExcelImportService.java
  13. +1
    -0
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/base/ImportBaseService.java
  14. +11
    -4
      easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/sax/SheetHandler.java
  15. +2
    -2
      easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiExcelTempUtil.java
  16. +193
    -0
      easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiWatermarkUtil.java
  17. +1
    -1
      easypoi-web/pom.xml
  18. +54
    -0
      easypoi-wps/pom.xml
  19. +136
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/controller/EasyPoiFileController.java
  20. +43
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/controller/EasyPoiUserController.java
  21. +48
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsFileEntity.java
  22. +40
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsFileHistoryEntity.java
  23. +19
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsToken.java
  24. +29
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsUserAclEntity.java
  25. +29
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsUserEntity.java
  26. +45
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsWatermarkEntity.java
  27. +16
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileHistoryRequest.java
  28. +16
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileHistoryResponse.java
  29. +20
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileResponse.java
  30. +22
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileSaveResponse.java
  31. +14
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsRenameRequest.java
  32. +21
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsResponse.java
  33. +15
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsUserRequest.java
  34. +17
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsUserResponse.java
  35. +85
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/EasyPoiWpsFileUtil.java
  36. +92
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/EasyPoiWpsUtil.java
  37. +216
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/IEasyPoiWpsService.java
  38. +19
    -0
      easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/IEasyPoiWpsUserService.java
  39. +38
    -0
      easypoi-wps/src/main/resources/META-INF/resources/easypoi-preview.html
  40. +6
    -0
      easypoi-wps/src/main/resources/META-INF/resources/easypoijs/jquery-1.9.1.min.js
  41. +1
    -0
      easypoi-wps/src/main/resources/META-INF/resources/easypoijs/polyfill.min.js
  42. +1
    -0
      easypoi-wps/src/main/resources/META-INF/resources/easypoijs/web-office-sdk-v1.1.2.umd.js
  43. +9
    -1
      history-cn.md
  44. +5
    -4
      pom.xml

+ 4
- 4
README-cn.md View File

@@ -134,22 +134,22 @@ https://oss.sonatype.org/content/groups/public/
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
```


+ 4
- 4
README.md View File

@@ -161,22 +161,22 @@ https://oss.sonatype.org/content/groups/public/
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.3</version>
<version>4.2.0</version>
</dependency>
```


+ 1
- 1
easypoi-annotation/pom.xml View File

@@ -4,7 +4,7 @@
<parent>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi</artifactId>
<version>4.1.3</version>
<version>4.2.0.A</version>
</parent>
<artifactId>easypoi-annotation</artifactId>
<description>base annotation</description>

+ 5
- 0
easypoi-annotation/src/main/java/cn/afterturn/easypoi/excel/annotation/Excel.java View File

@@ -67,6 +67,11 @@ public @interface Excel {
*/
public int imageType() default 1;
/**
* 文字前缀,如1234567890112242335 变成`1234567890112242335
*/
public String prefix() default "";
/**
* 文字后缀,如% 90 变成90%
*/


+ 6
- 2
easypoi-base/pom.xml View File

@@ -4,7 +4,7 @@
<parent>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi</artifactId>
<version>4.1.3</version>
<version>4.2.0.A</version>
</parent>
<artifactId>easypoi-base</artifactId>
<dependencies>
@@ -106,5 +106,9 @@
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
</dependencies>
</project>

+ 4
- 0
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/entity/params/ExcelExportEntity.java View File

@@ -84,6 +84,10 @@ public class ExcelExportEntity extends ExcelBaseEntity implements Comparable<Exc
* 合并依赖`
*/
private int[] mergeRely;
/**
* 前缀
*/
private String prefix;
/**
* 后缀
*/


+ 4
- 0
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/entity/params/ExcelImportEntity.java View File

@@ -44,6 +44,10 @@ public class ExcelImportEntity extends ExcelBaseEntity {
* 对应exportType
*/
private String classType;
/**
* 前缀
*/
private String prefix;
/**
* 后缀
*/


+ 4
- 0
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/export/base/ExportCommonService.java View File

@@ -223,6 +223,9 @@ public class ExportCommonService {
if (needHandlerList != null && needHandlerList.contains(entity.getName())) {
value = dataHandler.exportHandler(obj, entity.getName(), value);
}
if (StringUtils.isNotBlank(entity.getPrefix()) && value != null) {
value = entity.getPrefix() + value;
}
if (StringUtils.isNotEmpty(entity.getSuffix()) && value != null) {
value = value + entity.getSuffix();
}
@@ -262,6 +265,7 @@ public class ExportCommonService {
Integer.valueOf(PoiPublicUtil.getValueByTargetId(excel.orderNum(), targetId, "0")));
excelEntity.setWrap(excel.isWrap());
excelEntity.setExportImageType(excel.imageType());
excelEntity.setPrefix(excel.prefix());
excelEntity.setSuffix(excel.suffix());
excelEntity.setDatabaseFormat(excel.databaseFormat());
excelEntity.setFormat(


+ 1
- 1
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/export/template/ExcelExportOfTemplateUtil.java View File

@@ -175,7 +175,7 @@ public final class ExcelExportOfTemplateUtil extends BaseExportService {
private ExcelForEachParams getIndexColumn(List<ExcelForEachParams> columns) {
for (int i = 0; i < columns.size(); i++) {
if (INDEX.equals(columns.get(i).getConstValue())) {
if (columns.get(i) != null && INDEX.equals(columns.get(i).getConstValue())) {
columns.get(i).setConstValue("1");
return columns.get(i);
}


+ 7
- 7
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/html/helper/MergedRegionHelper.java View File

@@ -105,13 +105,6 @@ public class MergedRegionHelper {
public void shiftRows(Sheet sheet, int rowIndex, int size, int shiftRows) {
Set<String> keys = new HashSet<String>();
keys.addAll(mergedCache.keySet());
//删除掉原始的缓存KEY
for (String key : keys) {
String[] temp = key.split("_");
if (Integer.parseInt(temp[0]) >= rowIndex + size && Integer.parseInt(temp[0]) <= rowIndex + size + shiftRows) {
mergedCache.remove(key);
}
}
for (String key : keys) {
String[] temp = key.split("_");
if (Integer.parseInt(temp[0]) >= rowIndex) {
@@ -132,6 +125,13 @@ public class MergedRegionHelper {
}
}
}
//删除掉原始的缓存KEY
for (String key : keys) {
String[] temp = key.split("_");
if (Integer.parseInt(temp[0]) >= rowIndex + size && Integer.parseInt(temp[0]) <= rowIndex + size + shiftRows) {
mergedCache.remove(key);
}
}
}
}

+ 18
- 0
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/CellValueService.java View File

@@ -227,6 +227,7 @@ public class CellValueService {
result = cell;
}
if (entity != null) {
result = handlerPrefix(entity.getPrefix(), result);
result = handlerSuffix(entity.getSuffix(), result);
result = replaceValue(entity.getReplace(), result);
result = replaceValue(entity.getReplace(), result);
@@ -257,12 +258,29 @@ public class CellValueService {
Type[] ts = setMethod.getGenericParameterTypes();
String classFullName = ts[0].toString();
Object result = cellEntity.getValue();
result = handlerPrefix(entity.getPrefix(), result);
result = handlerSuffix(entity.getSuffix(), result);
result = replaceValue(entity.getReplace(), result);
result = handlerValue(dataHandler, object, result, titleString);
return getValueByType(classFullName, result, entity, (Class) ts[0]);
}

/**
* 把前缀删除掉
*
* @param result
* @param prefix
* @return
*/
private Object handlerPrefix(String prefix, Object result) {
if (StringUtils.isNotEmpty(prefix) && result != null
&& result.toString().startsWith(prefix)) {
String temp = result.toString();
return temp.substring(prefix.length(), temp.length());
}
return result;
}

/**
* 把后缀删除掉
*


+ 3
- 3
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/ExcelImportService.java View File

@@ -156,8 +156,8 @@ public class ExcelImportService extends ImportBaseService {
ImportParams params,
Map<String, PictureData> pictures) throws Exception {
List collection = new ArrayList();
Map<String, ExcelImportEntity> excelParams = new HashMap<String, ExcelImportEntity>();
List<ExcelCollectionParams> excelCollection = new ArrayList<ExcelCollectionParams>();
Map<String, ExcelImportEntity> excelParams = new HashMap<>();
List<ExcelCollectionParams> excelCollection = new ArrayList<>();
String targetId = null;
i18nHandler = params.getI18nHandler();
boolean isMap = Map.class.equals(pojoClass);
@@ -482,7 +482,7 @@ public class ExcelImportService extends ImportBaseService {
importResult.setWorkbook(removeSuperfluousRows(successBook, failRow, params));
importResult.setFailWorkbook(removeSuperfluousRows(book, successRow, params));
} else {
importResult.setWorkbook(successBook);
importResult.setWorkbook(book);
}
importResult.setFailList(failCollection);
importResult.setVerifyFail(verifyFail);


+ 1
- 0
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/base/ImportBaseService.java View File

@@ -70,6 +70,7 @@ public class ImportBaseService {
excelEntity.setSaveType(excel.imageType());
excelEntity.setReplace(excel.replace());
excelEntity.setDatabaseFormat(excel.databaseFormat());
excelEntity.setPrefix(excel.prefix());
excelEntity.setSuffix(excel.suffix());
excelEntity.setImportField(Boolean
.valueOf(PoiPublicUtil.getValueByTargetId(excel.isImportField(), targetId, "false")));


+ 11
- 4
easypoi-base/src/main/java/cn/afterturn/easypoi/excel/imports/sax/SheetHandler.java View File

@@ -55,7 +55,7 @@ public class SheetHandler extends DefaultHandler {
private int curCol = 0;
private CellValueType type;
private String currentLocation, prevLocation;
private String currentLocation = "A_", prevLocation;
private ISaxRowRead read;
@@ -74,8 +74,13 @@ public class SheetHandler extends DefaultHandler {
lastContents = "";
if (COL.equals(name)) {
String cellType = attributes.getValue(TYPE);
prevLocation = currentLocation;
currentLocation = attributes.getValue(ROW_COL);
if ("A_".equalsIgnoreCase(currentLocation)) {
currentLocation = attributes.getValue(ROW_COL);
prevLocation = "A" + getRowCell(currentLocation)[1];
} else {
prevLocation = currentLocation;
currentLocation = attributes.getValue(ROW_COL);
}
if (STRING.equals(cellType)) {
type = CellValueType.String;
return;
@@ -135,8 +140,9 @@ public class SheetHandler extends DefaultHandler {
} catch (Exception e) {
}
}
if (VALUE.equals(name) && StringUtils.isNotEmpty(prevLocation)) {
if ((COL.equals(name) || VALUE.equals(name)) && StringUtils.isNotEmpty(prevLocation)) {
addNullCell(prevLocation, currentLocation);
prevLocation = currentLocation;
}
//t元素也包含字符串
if (CellValueType.TElement.equals(type)) {
@@ -168,6 +174,7 @@ public class SheetHandler extends DefaultHandler {
rowList.clear();
curRow++;
curCol = 0;
currentLocation = "A_";
}
}


+ 2
- 2
easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiExcelTempUtil.java View File

@@ -8,8 +8,8 @@ import java.util.HashMap;
import java.util.Map;

/**
* poi 4.0 07版本在 shift操作下有bug,移动了单元格以及单元格样式,没有移动cell
* cell还是复用的原的cell,导致wb输出的时候没有输出值
* poi 4.0 07版本在 shift操作下有bug,移动了单元格以及单元格样式,没有移动cell
* cell还是复用的原的cell,导致wb输出的时候没有输出值
* 等待修复的时候删除这个问题
*
* @author by jueyue on 19-6-17.


+ 193
- 0
easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiWatermarkUtil.java View File

@@ -0,0 +1,193 @@
package cn.afterturn.easypoi.util;

import cn.afterturn.easypoi.cache.manager.POICacheManager;
import cn.afterturn.easypoi.exception.excel.ExcelExportException;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.ImageUtils;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlObject;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;

import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

/**
* 水印工具类,WPS仅支持打印水印
* 参考 https://jingyan.baidu.com/article/6d704a137cd29d28db51ca87.html
*
* @author jueyue on 20-4-29.
*/
public class PoiWatermarkUtil {

/**
* 为Excel打上水印工具函数仅支持XLSX格式
* @param sheet 需要打水印的Excel
* @param waterRemarkPath 水印地址,classPath,目前只支持png格式的图片,
* <p> 因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。 <p>
* @param position 位置 LEFT,CENTER,RIGHT
* @throws IOException
*/
public static void putWaterRemarkToExcel(Sheet sheet, String waterRemarkPath, String position) throws Exception {
int pictureIdx = sheet.getWorkbook().addPicture(IOUtils.toByteArray(POICacheManager.getFile(waterRemarkPath)), Workbook.PICTURE_TYPE_PNG);
OPCPackage opcpackage = ((XSSFWorkbook) sheet.getWorkbook()).getPackage();
PackagePartName partname = PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing" + pictureIdx + ".vml");
PackagePart part = opcpackage.createPart(partname, "application/vnd.openxmlformats-officedocument.vmlDrawing");
VmlDrawing vmldrawing = new VmlDrawing(part);
//创建页眉,位置LEFT,下面headerPos填写对应的
Header header = sheet.getHeader();
switch (position){
case "LEFT":
header.setLeft("&G");
vmldrawing.setHeaderPos("LH");
break;
case "CENTER":
header.setCenter("&G");
vmldrawing.setHeaderPos("CH");
break;
case "RIGHT":
header.setRight("&G");
vmldrawing.setHeaderPos("RH");
break;
default:
throw new ExcelExportException("输入的position参数不合法");
}
XSSFPictureData picData = (XSSFPictureData) sheet.getWorkbook().getAllPictures().get(pictureIdx);
String rIdPic = vmldrawing.addRelation(null, XSSFRelation.IMAGES, picData).getRelationship().getId();
ByteArrayInputStream is = new ByteArrayInputStream(picData.getData());
java.awt.Dimension imageDimension = ImageUtils.getImageDimension(is, picData.getPictureType());
IOUtils.closeQuietly(is);
vmldrawing.setRIdPic(rIdPic);
vmldrawing.setPictureTitle(waterRemarkPath);
vmldrawing.setImageDimension(imageDimension);

String rIdExtLink = ((XSSFSheet) sheet).addRelation(null, XSSFRelation.VML_DRAWINGS, vmldrawing).getRelationship().getId();
((XSSFSheet) sheet).getCTWorksheet().addNewLegacyDrawingHF().setId(rIdExtLink);
}

/**
* 为Excel打上水印工具函数仅支持XLSX格式
* @param sheet 需要打水印的Excel
* @param waterRemarkPath 水印地址,classPath,目前只支持png格式的图片,
* <p> 因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。 <p>
* @throws IOException
*/
public static void putWaterRemarkToExcel(Sheet sheet, String waterRemarkPath) throws Exception {
putWaterRemarkToExcel(sheet,waterRemarkPath,"LEFT");
}

static class VmlDrawing extends POIXMLDocumentPart {

String rIdPic = "";
String pictureTitle = "";
java.awt.Dimension imageDimension = null;
String headerPos = "";

VmlDrawing(PackagePart part) {
super(part);
}

void setRIdPic(String rIdPic) {
this.rIdPic = rIdPic;
}

void setPictureTitle(String pictureTitle) {
this.pictureTitle = pictureTitle;
}

void setHeaderPos(String headerPos) {
this.headerPos = headerPos;
}

void setImageDimension(java.awt.Dimension imageDimension) {
this.imageDimension = imageDimension;
}

@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
try {
// WPS测试通过版本
/*XmlObject doc = XmlObject.Factory.parse(

"<xml xmlns:oa=\"urn:schemas-microsoft-com:office:activation\"" +
" xmlns:p=\"urn:schemas-microsoft-com:office:powerpoint\"" +
" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"" +
" xmlns:o=\"urn:schemas-microsoft-com:office:office\"" +
" xmlns:v=\"urn:schemas-microsoft-com:vml\">" +
" <o:shapelayout v:ext=\"edit\">" +
" <o:idmap v:ext=\"edit\" data=\"1\"/>" +
" </o:shapelayout>" +
" <v:shape id=\""+headerPos+"\" " +
" o:spid=\"_x0000_s1028\" o:spt=\"75\" alt=\"" + pictureTitle + "\"" +
" type=\"#_x0000_t75\"" +
" style=\"position:absolute;left:0pt;top:0pt;margin-left:0pt;margin-top:0pt;height:" + (int) imageDimension.getHeight() + "pt;width:" + (int) imageDimension.getWidth() + "pt;\"" +
" filled=\"f\" o:preferrelative=\"t\" stroked=\"f\" coordsize=\"21600,21600\">" +
" <v:path/>" +
" <v:fill on=\"f\" focussize=\"0,0\"/>" +
" <v:stroke on=\"f\"/>" +
" <v:imagedata o:relid=\"" + rIdPic + "\" o:title=\"" + pictureTitle + "\"/>" +
" <o:lock v:ext=\"edit\" rotation=\"t\" aspectratio=\"t\"/>" +
" </v:shape>" +
"</xml>"

);*/
XmlObject doc = XmlObject.Factory.parse(

"<xml xmlns:v=\"urn:schemas-microsoft-com:vml\""
+ " xmlns:o=\"urn:schemas-microsoft-com:office:office\""
+ " xmlns:x=\"urn:schemas-microsoft-com:office:excel\">"
+ " <o:shapelayout v:ext=\"edit\">"
+ " <o:idmap v:ext=\"edit\" data=\"1\"/>"
+ " </o:shapelayout><v:shapetype id=\"_x0000_t75\" coordsize=\"21600,21600\" o:spt=\"75\""
+ " o:preferrelative=\"t\" path=\"m@4@5l@4@11@9@11@9@5xe\" filled=\"f\" stroked=\"f\">"
+ " <v:stroke joinstyle=\"miter\"/>"
+ " <v:formulas>"
+ " <v:f eqn=\"if lineDrawn pixelLineWidth 0\"/>"
+ " <v:f eqn=\"sum @0 1 0\"/>"
+ " <v:f eqn=\"sum 0 0 @1\"/>"
+ " <v:f eqn=\"prod @2 1 2\"/>"
+ " <v:f eqn=\"prod @3 21600 pixelWidth\"/>"
+ " <v:f eqn=\"prod @3 21600 pixelHeight\"/>"
+ " <v:f eqn=\"sum @0 0 1\"/>"
+ " <v:f eqn=\"prod @6 1 2\"/>"
+ " <v:f eqn=\"prod @7 21600 pixelWidth\"/>"
+ " <v:f eqn=\"sum @8 21600 0\"/>"
+ " <v:f eqn=\"prod @7 21600 pixelHeight\"/>"
+ " <v:f eqn=\"sum @10 21600 0\"/>"
+ " </v:formulas>"
+ " <v:path o:extrusionok=\"f\" gradientshapeok=\"t\" o:connecttype=\"rect\"/>"
+ " <o:lock v:ext=\"edit\" aspectratio=\"t\"/>"
+ " </v:shapetype><v:shape id=\"" + headerPos + "\" o:spid=\"_x0000_s1025\" type=\"#_x0000_t75\""
+ " style='position:absolute;margin-left:0;margin-top:0;"
+ "width:" + (int) imageDimension.getWidth() + "px;height:" + (int) imageDimension.getHeight() + "px;"
+ "z-index:1'>"
+ " <v:imagedata o:relid=\"" + rIdPic + "\" o:title=\"" + pictureTitle + "\"/>"
+ " <o:lock v:ext=\"edit\" rotation=\"t\"/>"
+ " </v:shape></xml>"

);
doc.save(out, DEFAULT_XML_OPTIONS);
out.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}

}

}

+ 1
- 1
easypoi-web/pom.xml View File

@@ -4,7 +4,7 @@
<parent>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi</artifactId>
<version>4.1.3</version>
<version>4.2.0.A</version>
</parent>
<artifactId>easypoi-web</artifactId>
<dependencies>


+ 54
- 0
easypoi-wps/pom.xml View File

@@ -0,0 +1,54 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi</artifactId>
<version>4.2.0</version>
</parent>
<artifactId>easypoi-wps</artifactId>
<dependencies>
<!--spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

+ 136
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/controller/EasyPoiFileController.java View File

@@ -0,0 +1,136 @@
package cn.afterturn.easypoi.wps.controller;

import cn.afterturn.easypoi.wps.entity.WpsToken;
import cn.afterturn.easypoi.wps.entity.resreq.*;
import cn.afterturn.easypoi.wps.service.IEasyPoiWpsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;

/**
* @author jueyue on 20-5-7.
*/
@RestController
@RequestMapping("easypoi/wps/v1/3rd/file")
public class EasyPoiFileController {

private static final Logger LOGGER = LoggerFactory.getLogger(EasyPoiFileController.class);

@Autowired(required = false)
private IEasyPoiWpsService easyPoiWpsService;

/**
* 获取网络文件预览URL
*
* @param filePath
* @return t
*/
@GetMapping("getViewUrl")
public WpsToken getViewUrl(String filePath) {
LOGGER.info("getViewUrlWebPath:filePath={}", filePath);
WpsToken token = easyPoiWpsService.getViewUrl(decode(filePath));
return token;
}

/**
* 获取文件元数据
*/
@GetMapping("info")
public WpsFileResponse getFileInfo(HttpServletRequest request, @RequestParam(value = "_w_userid", required = false) String userId,
@RequestParam("_w_filepath") String filePath) {
LOGGER.info("获取文件元数据userId:{},path:{}", userId, filePath);
String fileId = request.getHeader("x-weboffice-file-id");
WpsFileResponse fileResponse = easyPoiWpsService.getFileInfo(userId, decode(filePath), fileId);
return fileResponse;
}

/**
* 通知此文件目前有哪些人正在协作
*/
@PostMapping("online")
public WpsResponse fileOnline(HttpServletRequest request, @RequestBody WpsUserRequest list) {
LOGGER.info("通知此文件目前有哪些人正在协作param:{}", list);
String fileId = request.getHeader("x-weboffice-file-id");
easyPoiWpsService.fileOnline(fileId, list);
return WpsResponse.success();
}

/**
* 上传文件新版本
*/
@PostMapping("save")
public WpsFileSaveResponse fileSave(HttpServletRequest request,
@RequestParam(value = "_w_userid", required = false) String userId,
@RequestBody MultipartFile file) {
LOGGER.info("上传文件新版本");
String fileId = request.getHeader("x-weboffice-file-id");
return new WpsFileSaveResponse(easyPoiWpsService.fileSave(fileId, userId, file));
}

/**
* 获取特定版本的文件信息
*/
@GetMapping("version/{version}")
public WpsFileSaveResponse fileVersion(HttpServletRequest request, @PathVariable Integer version,
@RequestParam("_w_filepath") String filePath) {
LOGGER.info("获取特定版本的文件信息version:{}", version);
String fileId = request.getHeader("x-weboffice-file-id");
return new WpsFileSaveResponse(easyPoiWpsService.getFileInfoOfVersion(fileId, decode(filePath), version));
}

/**
* 文件重命名
*/
@PutMapping("rename")
public WpsResponse fileRename(HttpServletRequest request, @RequestBody WpsRenameRequest req,
@RequestParam(value = "_w_userid", required = false) String userId) {
LOGGER.info("文件重命名param:{},userId:{}", req, userId);
String fileId = request.getHeader("x-weboffice-file-id");
easyPoiWpsService.rename(fileId, userId, req.getName());
return WpsResponse.success();
}

/**
* 获取所有历史版本文件信息
*/
@PostMapping("history")
public WpsFileHistoryResponse fileHistory(@RequestBody WpsFileHistoryRequest req) {
LOGGER.info("获取所有历史版本文件信息param:{}", req);
return easyPoiWpsService.getHistory(req);
}

/**
* 新建文件
*/
@PostMapping("new")
public WpsResponse fileNew(@RequestBody MultipartFile file, @RequestParam(value = "_w_userid", required = false) String userId) {
LOGGER.info("新建文件,只打印不实现,userid:{}", userId);
return WpsResponse.success();
}

/**
* 回调通知
*/
@PostMapping("onnotify")
public WpsResponse onNotify(@RequestBody Map obj) {
LOGGER.info("回调通知,只打印不实现,param:{}", obj);
return WpsResponse.success();
}

public String decode(String filePath) {
try {
filePath = URLDecoder.decode(filePath, "UTF-8");
} catch (UnsupportedEncodingException e) {
LOGGER.error(e.getMessage(), e);
}
return filePath;
}

}

+ 43
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/controller/EasyPoiUserController.java View File

@@ -0,0 +1,43 @@
package cn.afterturn.easypoi.wps.controller;

import cn.afterturn.easypoi.wps.entity.WpsUserEntity;
import cn.afterturn.easypoi.wps.entity.resreq.WpsUserRequest;
import cn.afterturn.easypoi.wps.entity.resreq.WpsUserResponse;
import cn.afterturn.easypoi.wps.service.IEasyPoiWpsUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author jueyue on 20-5-8.
*/
@RestController
@RequestMapping("easypoi/wps/v1/3rd/file")
public class EasyPoiUserController {

private static final Logger LOGGER = LoggerFactory.getLogger(EasyPoiUserController.class);

@Autowired(required = false)
private IEasyPoiWpsUserService userService;

/**
* 获取用户信息
*/
@PostMapping("info")
public WpsUserResponse userInfo(@RequestBody WpsUserRequest list) {
LOGGER.info("获取用户信息param:{}", list);
WpsUserResponse response = new WpsUserResponse();
for (int i = 0; i < list.getIds().size(); i++) {
if (userService != null) {
response.getUsers().add(userService.getUser(list.getIds().get(i)));
} else {
response.getUsers().add(new WpsUserEntity());
}
}
return response;
}
}

+ 48
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsFileEntity.java View File

@@ -0,0 +1,48 @@
package cn.afterturn.easypoi.wps.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsFileEntity implements Serializable {
/**
* 文件id,字符串长度小于40
*/
private String id;
/**
* 文件名
*/
private String name;
/**
* 当前版本号,位数小于11
*/
private int version = 1;
/**
* 文件大小,单位为kb
*/
private int size;
/**
* 创建者id,字符串长度小于40
*/
private String creator = "0";
/**
* 修改者id,字符串长度小于40
*/
private String modifier;
/**
* 创建时间,时间戳,单位为秒
*/
private long create_time = System.currentTimeMillis();
/**
* 修改时间,时间戳,单位为秒
*/
private long modify_time;
private String download_url;

private WpsUserAclEntity user_acl = new WpsUserAclEntity();
private WpsWatermarkEntity watermark = new WpsWatermarkEntity();
}

+ 40
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsFileHistoryEntity.java View File

@@ -0,0 +1,40 @@
package cn.afterturn.easypoi.wps.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsFileHistoryEntity implements Serializable {

/**
* 文件id,字符串长度小于40
*/
private String id;
/**
* 文件名
*/
private String name;
/**
* 当前版本号,位数小于11
*/
private int version = 1;
/**
* 文件大小,单位为kb
*/
private int size;
/**
* 创建时间,时间戳,单位为秒
*/
private long create_time;
/**
* 修改时间,时间戳,单位为秒
*/
private long modify_time;

private WpsUserEntity creator;
private WpsUserEntity modifier;
}

+ 19
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsToken.java View File

@@ -0,0 +1,19 @@
package cn.afterturn.easypoi.wps.entity;

import cn.afterturn.easypoi.wps.entity.resreq.WpsResponse;
import lombok.Data;

import java.io.Serializable;

/**
* @author JueYue
* 界面的Token数据,默认不使用
*/
@Data
public class WpsToken extends WpsResponse implements Serializable {

private int expires_in;
private String token;
private String wpsUrl;

}

+ 29
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsUserAclEntity.java View File

@@ -0,0 +1,29 @@
package cn.afterturn.easypoi.wps.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsUserAclEntity implements Serializable {
/**
* 重命名权限,1为打开该权限,0为关闭该权限,默认为0
*/
private Integer rename = 0;
/**
* 历史版本权限,1为打开该权限,0为关闭该权限,默认为1
*/
private Integer history = 0;
/**
* 复制
*/
private Integer copy = 1;
/**
* 导出PDF
*/
private Integer export = 1;
private Integer print = 1;
}

+ 29
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsUserEntity.java View File

@@ -0,0 +1,29 @@
package cn.afterturn.easypoi.wps.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-7.
*/
@Data
public class WpsUserEntity implements Serializable {

/**
* 用户id,长度小于40
*/
private String id = "0";
/**
* 用户名称
*/
private String name = "悟耘-EasyPoi";
/**
* 用户操作权限,write:可编辑,read:预览
*/
private String permission = "read";
/**
* 用户头像地址
*/
private String avatar_url = "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=50688014,2596832035&fm=11&gp=0.jpg";
}

+ 45
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/WpsWatermarkEntity.java View File

@@ -0,0 +1,45 @@
package cn.afterturn.easypoi.wps.entity;

import lombok.Data;

import java.io.Serializable;

/**
* 水印配置
*
* @author jueyue on 20-5-8.
*/
@Data
public class WpsWatermarkEntity implements Serializable {
/**
* 水印类型, 0为无水印; 1为文字水印
*/
private Integer type = 0;
/**
* 文字水印的文字,当type为1时此字段必选
*/
private Integer value;
/**
* 水印的透明度,非必选,有默认值
* "rgba( 192, 192, 192, 0.6 )"
*/
private Integer fillstyle;
/**
* 水印的字体,非必选,有默认值
* "bold 20px Serif"
*/
private Integer font;
/**
* 水印的旋转度,非必选,有默认值
* -0.7853982
*/
private String rotate;
/**
* 水印水平间距,非必选,有默认值
*/
private Integer horizontal;
/**
* 水印垂直间距,非必选,有默认值
*/
private Integer vertical;
}

+ 16
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileHistoryRequest.java View File

@@ -0,0 +1,16 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsFileHistoryRequest extends WpsResponse implements Serializable {

private String id;
private int offset;
private int count;
}

+ 16
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileHistoryResponse.java View File

@@ -0,0 +1,16 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import cn.afterturn.easypoi.wps.entity.WpsFileHistoryEntity;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsFileHistoryResponse extends WpsResponse implements Serializable {

private List<WpsFileHistoryEntity> histories;
}

+ 20
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileResponse.java View File

@@ -0,0 +1,20 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import cn.afterturn.easypoi.wps.entity.WpsFileEntity;
import cn.afterturn.easypoi.wps.entity.WpsUserEntity;
import lombok.Data;

import java.io.Serializable;

/**
* 获取文件返回对象
*
* @author jueyue on 20-5-8.
*/
@Data
public class WpsFileResponse extends WpsResponse implements Serializable {

private WpsFileEntity file;

private WpsUserEntity user = new WpsUserEntity();
}

+ 22
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsFileSaveResponse.java View File

@@ -0,0 +1,22 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import cn.afterturn.easypoi.wps.entity.WpsFileEntity;
import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsFileSaveResponse extends WpsResponse implements Serializable {

public WpsFileSaveResponse() {
}

public WpsFileSaveResponse(WpsFileEntity file) {
this.file = file;
}

private WpsFileEntity file;
}

+ 14
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsRenameRequest.java View File

@@ -0,0 +1,14 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsRenameRequest extends WpsResponse implements Serializable {

private String name;
}

+ 21
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsResponse.java View File

@@ -0,0 +1,21 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import lombok.Data;

import java.io.Serializable;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsResponse implements Serializable {

private int code = 200;

private String msg;
private String status = "success";

public static WpsResponse success() {
return new WpsResponse();
}
}

+ 15
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsUserRequest.java View File

@@ -0,0 +1,15 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsUserRequest implements Serializable {

List<String> ids;
}

+ 17
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/entity/resreq/WpsUserResponse.java View File

@@ -0,0 +1,17 @@
package cn.afterturn.easypoi.wps.entity.resreq;

import cn.afterturn.easypoi.wps.entity.WpsUserEntity;
import lombok.Data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
* @author jueyue on 20-5-8.
*/
@Data
public class WpsUserResponse extends WpsResponse implements Serializable {

private List<WpsUserEntity> users = new ArrayList<>();
}

+ 85
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/EasyPoiWpsFileUtil.java View File

@@ -0,0 +1,85 @@
package cn.afterturn.easypoi.wps.service;

/**
* @author jueyue on 20-5-8.
*/
public class EasyPoiWpsFileUtil {

private static String[] OFFICE = {"word", "excel", "ppt"};

private static String[] EXCEL_EXTS = {"et", "xls", "xlt", "xlsx", "xlsm", "xltx", "xltm", "csv"};

private static String[] WORD_EXTS = {"doc", "docx", "txt", "dot", "wps", "wpt", "dotx", "docm", "dotm"};

private static String[] PPT_EXTS = {"ppt", "pptx", "pptm", "pptm", "ppsm", "pps", "potx", "potm", "dpt", "dps"};

private static String[] PDF_EXTS = {"pdf"};

public static String getFileTypeCode(String fileType) {
for (String et : EXCEL_EXTS) {
if (et.equalsIgnoreCase(fileType)) {
return "s";
}
}
for (String et : WORD_EXTS) {
if (et.equalsIgnoreCase(fileType)) {
return "w";
}
}
for (String et : PPT_EXTS) {
if (et.equalsIgnoreCase(fileType)) {
return "p";
}
}
for (String et : PDF_EXTS) {
if (et.equalsIgnoreCase(fileType)) {
return "f";
}
}
return null;
}

public static boolean checkCode(String fileType) {
for (String et : OFFICE) {
if (et.equalsIgnoreCase(fileType)) {
return true;
}
}
return false;
}

public static String getTypeCode(String fileType) {
if ("word".equalsIgnoreCase(fileType)) {
return "w";
}
if ("excel".equalsIgnoreCase(fileType)) {
return "s";
}
if ("ppt".equalsIgnoreCase(fileType)) {
return "p";
}
return null;
}

public static String getFileName(String filePath) {
String[] pathArr = filePath.split("/");
String fileName;
if (pathArr.length > 1) {
fileName = pathArr[pathArr.length - 1];
} else {
fileName = filePath;
}
return fileName;
}

public static String getFileTypeByPath(String filePath) {
String fileName = getFileName(filePath);
String[] arr = fileName.split("\\.");
return arr[arr.length - 1];
}

public static String getFileTypeByName(String fileName) {
String[] arr = fileName.split("\\.");
return arr[arr.length - 1];
}
}

+ 92
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/EasyPoiWpsUtil.java View File

@@ -0,0 +1,92 @@
package cn.afterturn.easypoi.wps.service;

import org.apache.commons.codec.digest.HmacUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.commons.codec.binary.Base64.encodeBase64String;

/**
* Wps相关的工具类
*
* @author jueyue on 20-5-8.
*/
public class EasyPoiWpsUtil {



public static String getKeyValueStr(Map<String, String> params) {
List<String> keys = new ArrayList<String>() {
{
for (Map.Entry<String, String> entry : params.entrySet()) {
add(entry.getKey());
}
}
};
StringBuilder sb = new StringBuilder();
for (String key : keys) {
String value = params.get(key) + "&";
sb.append(key).append("=").append(value);
}
return sb.toString();
}

public static String getSignature(Map<String, String> params, String appSecret) {
List<String> keys = new ArrayList<String>() {
{
for (Map.Entry<String, String> entry : params.entrySet()) {
add(entry.getKey());
}
}
};

// 将所有参数按key的升序排序
keys.sort(String::compareTo);

// 构造签名的源字符串
StringBuilder contents = new StringBuilder();
for (String key : keys) {
if (key.equals("_w_signature")) {
continue;
}
contents.append(key).append("=").append(params.get(key));
}
contents.append("_w_secretkey=").append(appSecret);

// 进行hmac sha1 签名
byte[] bytes = HmacUtils.hmacSha1(appSecret.getBytes(), contents.toString().getBytes());

//字符串经过Base64编码
String sign = encodeBase64String(bytes);
try {
return URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}

public Map<String, String> paramToMap(String paramStr) {
String[] params = paramStr.split("&");
return new HashMap<String, String>() {
{
for (String param1 : params) {
String[] param = param1.split("=");
if (param.length >= 2) {
String key = param[0];
StringBuilder value = new StringBuilder(param[1]);
for (int j = 2; j < param.length; j++) {
value.append("=").append(param[j]);
}
put(key, value.toString());
}
}
}
};
}
}

+ 216
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/IEasyPoiWpsService.java View File

@@ -0,0 +1,216 @@
package cn.afterturn.easypoi.wps.service;

import cn.afterturn.easypoi.wps.entity.WpsFileEntity;
import cn.afterturn.easypoi.wps.entity.WpsToken;
import cn.afterturn.easypoi.wps.entity.resreq.WpsFileHistoryRequest;
import cn.afterturn.easypoi.wps.entity.resreq.WpsFileHistoryResponse;
import cn.afterturn.easypoi.wps.entity.resreq.WpsFileResponse;
import cn.afterturn.easypoi.wps.entity.resreq.WpsUserRequest;
import org.springframework.web.multipart.MultipartFile;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
* 获取
*
* @author jueyue on 20-5-7.
*/
public interface IEasyPoiWpsService {
/**
* 获取Wps的地址
*
* @param filePath
* @return
*/
default WpsToken getViewUrl(String filePath) {
WpsToken t = new WpsToken();
Map<String, String> values = new HashMap<String, String>() {
{
put("_w_appid", getAppId());
put("_w_userid", getUserId());
put("_w_filepath", filePath);
}
};
String keyValueStr = EasyPoiWpsUtil.getKeyValueStr(values);
String signature = EasyPoiWpsUtil.getSignature(values, getAppSecret());
String fileTypeCode = EasyPoiWpsFileUtil.getFileTypeCode(EasyPoiWpsFileUtil.getFileTypeByPath(filePath));

String wpsUrl = getDomain() + fileTypeCode + "/" + getFileId(filePath) + "?"
+ keyValueStr + "_w_signature=" + signature;
t.setToken(getToken());
t.setExpires_in(600);
t.setWpsUrl(wpsUrl);

return t;
}

/**
* 获取用户Token有必要可以带上
*
* @return
*/
default String getToken() {
return UUID.randomUUID().toString().replace("-", "");
}

/**
* 获取文件ID,如果filePath可以现实没必要,如果使用ID请实现
*
* @param filePath
* @return
*/
default String getFileId(String filePath) {
return UUID.randomUUID().toString().replace("-", "");
}

/**
* WPS路径
*
* @return
*/
default String getDomain() {
return "https://wwo.wps.cn/office/";
}

/**
* APP秘钥
*
* @return
*/
String getAppSecret();

/**
* 获取WPS配置的AppId
*
* @return
*/
String getAppId();

/**
* 获取当前用户ID,如果不权限校验可以不实现
*
* @return
*/
default String getUserId() {
return "0";
}

/**
* 获取文件信息
*
* @param userId
* @param filepath
* @param fileId
* @return 返回文件信息
*/
default WpsFileResponse getFileInfo(String userId, String filepath, String fileId) {
WpsFileResponse response = new WpsFileResponse();
WpsFileEntity fileEntity = new WpsFileEntity();
fileEntity.setId(fileId);
fileEntity.setName(getFileName(filepath));
fileEntity.setSize(getFileSize(filepath));
fileEntity.setDownload_url(getDownLoadUrl(filepath));
response.setFile(fileEntity);
return response;
}

/**
* 单位为B
*
* @param filepath
* @return
*/
int getFileSize(String filepath);

/**
* 获取文件的下载路径
*
* @param filepath
* @return
*/
String getDownLoadUrl(String filepath);

/**
* 获取文件名称 -中文或者英文
*
* @param filepath
* @return
*/
default String getFileName(String filepath) {
return EasyPoiWpsFileUtil.getFileName(filepath);
}

/**
* 文件被那些客户协作
*
* @param fileId
* @param list
*/
default void fileOnline(String fileId, WpsUserRequest list) {
}

/**
* 保存文件
*
* @param fileId
* @param userId
* @param file
* @return
*/
default WpsFileEntity fileSave(String fileId, String userId, MultipartFile file) {
throw new NotImplementedException();
}

/**
* 获取特定版本的文件
*
* @param fileId
* @param filepath
* @param version
* @return
*/
default WpsFileEntity getFileInfoOfVersion(String fileId, String filepath, Integer version) {
WpsFileEntity fileEntity = new WpsFileEntity();
fileEntity.setId(fileId);
fileEntity.setName(getFileName(filepath));
fileEntity.setDownload_url(getDownLoadUrl(filepath, version));
fileEntity.setModifier(fileEntity.getModifier());
fileEntity.setModify_time(System.currentTimeMillis());
return fileEntity;
}

/**
* 获取特定版本的URL
*
* @param filepath
* @param version
* @return
*/
default String getDownLoadUrl(String filepath, Integer version) {
throw new NotImplementedException();
}

/**
* 文件重命名
*
* @param fileId
* @param userId
* @param name
*/
default void rename(String fileId, String userId, String name) {
throw new NotImplementedException();
}

/**
* 获取文件历史版本
*
* @param req
* @return
*/
default WpsFileHistoryResponse getHistory(WpsFileHistoryRequest req) {
throw new NotImplementedException();
}
}

+ 19
- 0
easypoi-wps/src/main/java/cn/afterturn/easypoi/wps/service/IEasyPoiWpsUserService.java View File

@@ -0,0 +1,19 @@
package cn.afterturn.easypoi.wps.service;

import cn.afterturn.easypoi.wps.entity.WpsUserEntity;

/**
* 用户服务
*
* @author jueyue on 20-5-8.
*/
public interface IEasyPoiWpsUserService {

/**
* 获取用户信息
*
* @param userId
* @return
*/
WpsUserEntity getUser(String userId);
}

+ 38
- 0
easypoi-wps/src/main/resources/META-INF/resources/easypoi-preview.html View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>预览</title>
<script src="/easypoijs/jquery-1.9.1.min.js"></script>
<script src="/easypoijs/polyfill.min.js"></script>
<script src="/easypoijs/web-office-sdk-v1.1.2.umd.js"></script>
<script>
$(document).ready(function () {
let filePath = getUrlParam('filePath');
$.get('v1/3rd/file/getViewUrl?filePath=' + filePath, function (data) {
let easyWps = WebOfficeSDK.config({
mode: 'simple',
url: data.wpsUrl, // 如果需要通过js-sdk传递token方式鉴权,则需要包含_w_tokentype=1参数
//mount: document.querySelector('#easypoi-wps-mount')
})
easyWps.setToken({token: data.token})
// 如果需要对iframe进行特殊的处理,可以通过以下方式拿到iframe的dom对象
//console.log(easyWps.iframe)
// 打开文档结果
easyWps.on('fileOpen', function (data) {
console.log(data.success)
})
})
});

function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
var r = window.location.search.substr(1).match(reg); //匹配目标参数
if (r != null) return decodeURI(r[2]);
return null; //返回参数值
}
</script>
</head>
<body>
</body>
</html>

+ 6
- 0
easypoi-wps/src/main/resources/META-INF/resources/easypoijs/jquery-1.9.1.min.js
File diff suppressed because it is too large
View File


+ 1
- 0
easypoi-wps/src/main/resources/META-INF/resources/easypoijs/polyfill.min.js View File

@@ -0,0 +1 @@
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n():"function"==typeof define&&define.amd?define(n):n()}(0,function(){"use strict";function e(e){var n=this.constructor;return this.then(function(t){return n.resolve(e()).then(function(){return t})},function(t){return n.resolve(e()).then(function(){return n.reject(t)})})}function n(e){return!(!e||"undefined"==typeof e.length)}function t(){}function o(e){if(!(this instanceof o))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],c(e,this)}function r(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null!==t){var o;try{o=t(e._value)}catch(r){return void f(n.promise,r)}i(n.promise,o)}else(1===e._state?i:f)(n.promise,e._value)})):e._deferreds.push(n)}function i(e,n){try{if(n===e)throw new TypeError("A promise cannot be resolved with itself.");if(n&&("object"==typeof n||"function"==typeof n)){var t=n.then;if(n instanceof o)return e._state=3,e._value=n,void u(e);if("function"==typeof t)return void c(function(e,n){return function(){e.apply(n,arguments)}}(t,n),e)}e._state=1,e._value=n,u(e)}catch(r){f(e,r)}}function f(e,n){e._state=2,e._value=n,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;t>n;n++)r(e,e._deferreds[n]);e._deferreds=null}function c(e,n){var t=!1;try{e(function(e){t||(t=!0,i(n,e))},function(e){t||(t=!0,f(n,e))})}catch(o){if(t)return;t=!0,f(n,o)}}var a=setTimeout;o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var o=new this.constructor(t);return r(this,new function(e,n,t){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof n?n:null,this.promise=t}(e,n,o)),o},o.prototype["finally"]=e,o.all=function(e){return new o(function(t,o){function r(e,n){try{if(n&&("object"==typeof n||"function"==typeof n)){var u=n.then;if("function"==typeof u)return void u.call(n,function(n){r(e,n)},o)}i[e]=n,0==--f&&t(i)}catch(c){o(c)}}if(!n(e))return o(new TypeError("Promise.all accepts an array"));var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var f=i.length,u=0;i.length>u;u++)r(u,i[u])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(t,r){if(!n(e))return r(new TypeError("Promise.race accepts an array"));for(var i=0,f=e.length;f>i;i++)o.resolve(e[i]).then(t,r)})},o._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};var l=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof global)return global;throw Error("unable to locate global object")}();"Promise"in l?l.Promise.prototype["finally"]||(l.Promise.prototype["finally"]=e):l.Promise=o});

+ 1
- 0
easypoi-wps/src/main/resources/META-INF/resources/easypoijs/web-office-sdk-v1.1.2.umd.js
File diff suppressed because it is too large
View File


+ 9
- 1
history-cn.md View File

@@ -2,7 +2,15 @@
--------------------------
版本修改
--------------------------
- 4.1.3
- 4.2.0
- 增加wps模块
- 模板添加了index常量列
- 修复横向迭代的时候,合并问题
- 添加XLSX水印工具类
- 修复 SAX SheetHandler 特殊情境下导致列错位
- 横向循环的时候同步宽度设置
- 注解支持生成下拉选择
- 4.1.3
- csv导出模式修改为write
- 4.1.2
- 修复shift时候最后一行问题


+ 5
- 4
pom.xml View File

@@ -3,13 +3,14 @@
<modelVersion>4.0.0</modelVersion>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi</artifactId>
<version>4.1.3</version>
<version>4.2.0.A</version>
<packaging>pom</packaging>
<name>easypoi</name>
<modules>
<module>easypoi-annotation</module>
<module>easypoi-base</module>
<module>easypoi-web</module>
<module>easypoi-annotation</module>
<module>easypoi-wps</module>
</modules>

<url>http://opensource.afterturn.cn/</url>
@@ -45,12 +46,12 @@
</organization>

<properties>
<sub.version>4.1.3</sub.version>
<sub.version>4.2.0</sub.version>
<poi.version>4.1.1</poi.version>
<xerces.version>2.9.1</xerces.version>
<guava.version>16.0.1</guava.version>
<commons-lang.version>3.2.1</commons-lang.version>
<slf4j.version>1.6.1</slf4j.version>
<slf4j.version>1.7.26</slf4j.version>
<spring.version>5.1.7.RELEASE</spring.version>
</properties>
<dependencyManagement>


Loading…
Cancel
Save