wpsOffice文件在线预览
wpsoffice开发文档地址:https://wwo.wps.cn/docs/
hint:申请服务通过后需填写回调地址,请填写你的服务器公网可访问的地址。
并且项目需要部署到你的公网可访问的服务器上。
一:添加model类
由于官方demo是完全无需引入依赖的,所以可将model包下类直接复制到自己项目中
//model类1
@Component
public class ApplicationProperties implements CommandLineRunner {
public static String appid = "";
public static String appSecret = "";
public static String domain = "";
@Autowired
public ApplicationProperties(
@Value("${appid}") String appid,
@Value("${appsecret}") String appSecret,
@Value("${download_host}") String download_host,
@Value("${domain}") String domain) {
ApplicationProperties.appid = appid;
ApplicationProperties.appSecret = appSecret;
ApplicationProperties.domain = domain;
TODO: 下载链接按实际情况增改参数
// if (download_host != null)
// FileModel.download_url = download_host + "/weboffice/getFile?_w_fileid=";
}
@Override
public void run(String... args) throws Exception {
}
}
public class FileInfoModel {
FileModel file = new FileModel();
UserModel user = new UserModel();
}
//值是自定义的,我测试用的顺便写的参数
public class FileModel {
public String id = "111";
public String name = "1.doc";
public long version = 3;
public long size = 2000;
public String creator = "1231";
public String modifier = "1231";
public static String download_url = "";
}
public class UrlModel {
public String wpsUrl;
public String token;
}
public class UserModel {
public String id = "xxx";
public String name ="xxx";
public String permission = "read"; //read-在线预览 write-在线编辑
public String avatar_url = "xxx";
}
二:配置文件application.yml
domain: https://wwo.wps.cn #无需改动
appid: xxx
appkey: xxx
download_host: xxx #根据需要配置
appsecret: xxx #用于加密的盐,自定义
三:实现回调接口
3.1-根据文件id生成wps的url
@RestController
public class OauthController {
//自定义的ppt服务接口,用于在数据库中维护文件信息
@Autowired
private IPptFileService pptFileService;
private static Map<String, String> fileTypeMap = new HashMap<String, String>();
TODO: 参数传递最好不要出现中文等特殊字符,容易导致签名不过等问题,本例子用fileid与文件名做了一个映射,实际开发可以按情况处理
static {
fileTypeMap.put("1", "w");
fileTypeMap.put("2", "s");
fileTypeMap.put("3", "p");
fileTypeMap.put("4", "f");
}
// @PassToken
@RequestMapping(value="/weboffice/url", method = RequestMethod.GET)
@ResponseBody
public CommonResult getapp_Token(@RequestParam("_w_fileid") String fileid) throws UnsupportedEncodingException {
if (fileid == null || fileid.isEmpty()) {
return null;
}
LambdaQueryWrapper<PptFile> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(PptFile::getFileKey,fileid);
PptFile one = pptFileService.getOne(queryWrapper);
if(one.getFileId()!=null){
fileid=one.getFileId();
}else{
UUID uuid = UUID.randomUUID();
String replace = uuid.toString().replace("-", "");
one.setFileId(replace);
one.setUpdateTime(new Date());
fileid=replace;
pptFileService.updateById(one);
}
String url = ApplicationProperties.domain + "/office/" + "p" + "/" + fileid + "?" ;
TODO: 注意:签名前,参数不要urlencode,要签名以后统一处理url编码,防止签名不过,带中文等字符容易导致签名不过,要注意签名与编成的顺序,最好不要带中文等特殊字符
Map paramMap= new HashMap<String, String>();
paramMap.put("_w_appid", ApplicationProperties.appid);
paramMap.put("_w_fileid", fileid);
String signature = getSignature(paramMap, ApplicationProperties.appSecret);
url += getUrlParam(paramMap) + "&_w_signature=" + signature;
UrlModel urlModel = new UrlModel();
urlModel.wpsUrl = url;
urlModel.token = "abc";
return CommonResult.success(urlModel);
}
private static String getUrlParam(Map<String, String> params) throws UnsupportedEncodingException {
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (builder.length() > 0) {
builder.append('&');
}
builder.append(URLEncoder.encode(entry.getKey(), "utf-8")).append('=').append(URLEncoder.encode(entry.getValue(), "utf-8"));
}
return builder.toString();
}
private static String getSignature(Map<String, String> params, String appSecret) {
List<String> keys=new ArrayList();
for (Map.Entry<String, String> entry : params.entrySet()) {
keys.add(entry.getKey());
}
// 将所有参数按key的升序排序
Collections.sort(keys, new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
// 构造签名的源字符串
StringBuilder contents=new StringBuilder("");
for (String key : keys) {
if (key=="_w_signature"){
continue;
}
contents.append(key+"=").append(params.get(key));
System.out.println("key:"+key+",value:"+params.get(key));
}
contents.append("_w_secretkey=").append(appSecret);
// 进行hmac sha1 签名
byte[] bytes= hmacSha1(appSecret.getBytes(),contents.toString().getBytes());
//字符串经过Base64编码
String sign= encodeBase64String(bytes);
try {
sign = URLEncoder.encode( sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(sign);
return sign;
}
public static byte[] hmacSha1(byte[] key, byte[] data) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = Mac.getInstance(signingKey.getAlgorithm());
mac.init(signingKey);
return mac.doFinal(data);
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
}
3.2-文件信息回调接口
@RestController
public class WebOfficeController {
@Autowired
private IPptFileService pptFileService;
//我在项目中使用了腾讯云存储服务,需要了解接入腾讯云存储的朋友可看我腾讯云存储的文章
//url:https://blog.csdn.net/qq_50990903/article/details/118615261?spm=1001.2014.3001.5501
@Autowired
private QCloudStorageService storageService;
@Autowired
private TencentCosConfig tencentCosConfig;
@Autowired
private COSClient cosStsClient;
TODO: 参数传递最好不要出现中文等特殊字符,容易导致签名不过等问题,本例子用fileid与文件名做了一个映射,实际开发可以按情况处理
private static Map<String, String> fileNameMap = new HashMap<String, String>();
static {
fileNameMap.put("1", "中文.doc");
fileNameMap.put("2", "2.xls");
fileNameMap.put("3", "3.ppt");
}
@PassToken
@RequestMapping(value="/v1/3rd/file/info", method = RequestMethod.GET)
@ResponseBody
public Object fileInfo(@RequestParam("_w_fileid") String fileid) throws Exception {
JSONObject jsonObject = new JSONObject();
JSONObject file = new JSONObject();
JSONObject user = new JSONObject();
LambdaQueryWrapper<PptFile> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(PptFile::getFileId,fileid);
PptFile one = pptFileService.getOne(queryWrapper);
try {
FileModel fileModel = new FileModel();
TODO: 文件的id应该唯一
file.put("id", fileid);
file.put("name", fileid);
TODO: 文件的版本控制
file.put("version", fileModel.version);
TODO: 必须返回文件真实大小,服务端会检查
file.put("size", one.getFileSize());
file.put("create_time",new Date().getTime()/1000);
file.put("modify_time",new Date().getTime()/1000);
file.put("creator", fileModel.creator);
file.put("modifier", fileModel.modifier);
TODO: 下载链接中的参数如带中文等特殊字符,参数必须进行urlencode
//从腾讯云获取下载链接
Date date = new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000);
URL url = cosStsClient.generatePresignedUrl(tencentCosConfig.getQcloudBucketName(), one.getFileKey(), date);
String download_url=url.toString();
file.put("download_url", download_url);
jsonObject.put("file", file);
UserModel userModel = new UserModel();
user.put("id", userModel.id);
user.put("name", userModel.name);
user.put("permission", "read");
user.put("avatar_url", userModel.avatar_url);
jsonObject.put("user", user);
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject.toString();
}
@PassToken
@RequestMapping(value="/v1/3rd/file/version/{version}", method = RequestMethod.GET)
@ResponseBody
public Object fileVersionInfo(@PathVariable("version") Long version, @RequestParam("_w_fileid") String fileid) throws UnsupportedEncodingException {
JSONObject jsonObject = new JSONObject();
JSONObject file = new JSONObject();
JSONObject user = new JSONObject();
try {
FileModel fileModel = new FileModel();
File localFile = new File(fileNameMap.get(fileid));
fileModel.size = localFile.length();
TODO: 文件的id应该唯一
file.put("id", fileid);
file.put("name", fileNameMap.get(fileid));
TODO: 文件的版本控制
file.put("version", version);
TODO: 必须返回文件真实大小,服务端会检查
file.put("size", fileModel.size);
file.put("creator", fileModel.creator);
file.put("modifier", fileModel.modifier);
TODO: 下载链接中的参数如带中文等特殊字符,参数必须进行urlencode
file.put("download_url", fileModel.download_url + fileid);
jsonObject.put("file", file);
UserModel userModel = new UserModel();
user.put("id", userModel.id);
user.put("name", userModel.name);
user.put("permission", "write");
user.put("avatar_url", userModel.avatar_url);
jsonObject.put("user", user);
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject.toString();
}
@PassToken
@RequestMapping(value="/v1/3rd/user/info", method = RequestMethod.POST)
@ResponseBody
public Object userInfo() {
JSONObject jsonObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
JSONObject user = new JSONObject();
UserModel userModel = new UserModel();
try {
user.put("id", userModel.id);
user.put("name", userModel.name);
user.put("permission", userModel.permission);
user.put("avatar_url", userModel.avatar_url);
jsonArray.put(user);
jsonObject.put("users", jsonArray);
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject.toString();
}
@PassToken
@RequestMapping(value="/v1/3rd/file/online", method = RequestMethod.POST)
@ResponseBody
public CommonResult online() {
return CommonResult.success();
}
@PassToken
@RequestMapping(value = "/v1/3rd/file/save", method = RequestMethod.POST)
@ResponseBody
public Object save(@RequestParam("file") MultipartFile file, @RequestParam("_w_fileid") String fileid) {
if (!file.isEmpty()) {
try {
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(new File(fileNameMap.get(fileid))));
out.write(file.getBytes());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
TODO: 返回保存后的文件信息 特别是文件大小与版本信息要准确
FileModel filemodel = new FileModel();
filemodel.name = fileNameMap.get(fileid);
filemodel.size = file.getSize();
filemodel.version = filemodel.version + 1;
return filemodel;
}
/**
* 回调通知
*/
@PostMapping("v1/3rd/onnotify")
public CommonResult onNotify() {
// logger.info("回调通知param:{}", JSON.toJSONString(obj));
// TODO
// 返回数据暂不处理
return CommonResult.success();
}
/*@PassToken
@GetMapping("/weboffice/getFile")
public ResponseEntity<byte[]> getFile(@RequestParam("_w_fileid") String fileid) throws Exception {
TODO: 处理文件下载,返回对应的文件,如果是接第三方存储,可以没有这个接口
File file = new File(fileNameMap.get(fileid));
InputStream inputStream = new FileInputStream(file);
byte[] body = new byte[inputStream.available()];
HttpHeaders headers=new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileNameMap.get(fileid), "utf-8"));
inputStream.read(body);
return new ResponseEntity(body, headers, HttpStatus.OK);
}*/
}
版权声明:本文为qq_50990903原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。