本人技術小白一枚,前些天老大讓我寫一個office在線預覽的一個功能,跟百度網盤類似,各種找資料,總結一下我覺得比較好用的方法。
網上大概有這幾種office在線預覽的方法。
# 第一種
利用office online實現在線預覽,Office平臺提供了通過url的指向達到預覽效果。
http://view.officeapps.live.com/op/view.aspx?src=
後面的src填寫文檔上傳到服務器的地址,地址需要通過用URLEncode進行編譯。
例:
http://view.officeapps.live.com/op/view.aspx?src=http%3a%2f%2fvideo.ch9.ms%2fbuild%2f2011%2fslides%2fTOOL-532T_Sutter.pptx
參照鏈接:
https://blog.csdn.net/csdn_cjgu/article/details/69389474
優點:這個功能由Office提供所以只需要拼接地址。
缺點:文檔的訪問地址不能直接使用 ip,需要通過域名訪問,並且端口必須是 80 端口,Word、ppt文檔的大小不能超過10M,Excel不能超過5M
# 第二種
1.通過第三方工具openoffice,將word、excel、ppt、txt等文件轉換爲pdf文件,
2.通過swfTools將pdf文件轉換成swf格式的文件;
3.通過FlexPaper文檔組件在頁面上進行展示。
參照鏈接:
https://blog.csdn.net/tmac937436/article/details/70799687?locationNum=14&fps=1
總結一下這種方法的利弊
優點:openoffice有各種版本,支持跨平臺,轉換速度快;
缺點:轉換的樣式會有缺損,Excel和openoffice完美不兼容 = . = ,轉換的時候會出現折行,切分等情況,效果很不理想;
FlexPaper這個是用Flash插件顯示的,展示的效果優點low。
# 第三種
利用poi實現office在線預覽
public static void PoiWord07ToHtml (HttpServletRequest request) throws IOException{
String path= "C:\\Users\\Administrator\\Desktop\\";
String file = "C:\\Users\\Administrator\\Desktop\\word07.docx";
String file2 ="C:\\Users\\Administrator\\Desktop\\word07.html";
File f = new File(file);
if (!f.exists()) {
System.out.println("Sorry File does not Exists!");
} else {
if (f.getName().endsWith(".docx") || f.getName().endsWith(".DOCX")) {
//讀取文檔內容
InputStream in = new FileInputStream(f);
XWPFDocument document = new XWPFDocument(in);
File imageFolderFile = new File(path);
//加載html頁面時圖片路徑
XHTMLOptions options = XHTMLOptions.create().URIResolver( new BasicURIResolver("./"));
//圖片保存文件夾路徑
options.setExtractor(new FileImageExtractor(imageFolderFile));
OutputStream out = new FileOutputStream(new File(file2));
XHTMLConverter.getInstance().convert(document, out, options);
out.close();
} else {
System.out.println("Enter only MS Office 2007+ files");
}
}
}
總結一下這種方法的利弊
優點:純java代碼不需要第三方軟件,poi對於Excel的解析比較好,可以完美轉換。
缺點:jar包真的好難找啊,各種版本不兼容問題,比如word03和word07生成的分別是.doc和docx,poi對於.doc不識別,然後各種報錯,由於生成的是Html所以它會把Word中的圖片單獨存放在一個文件下很佔空間。
# 第四種
使用jacob實現office轉換pdf達到預覽功能。
pom文件中引用
<dependency>
<groupId>net.sf.jacob-project</groupId>
<artifactId>jacob</artifactId>
<version>1.14.3</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
</dependency>
<!--poi-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14-beta1</version>
</dependency>
網上查找jacob對應版本包把jacob-1.14.3-x64.dll複製到需要在Java\jdk1.8.0\jre\bin目錄下,
經過多次測試發現jacob對於Excel的轉換有些問題,所以Excel的轉換我用的是poi。
自定義一個工具類Word2Pdf
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import java.io.*;
public class Word2Pdf {
static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
static final int wdFormatPDF = 17;// word轉PDF 格式
static final int ppSaveAsPDF = 32;// ppt 轉PDF 格式
public static void main(String[] args) throws IOException {
}
public void word2pdf(String wordPath,String target,String wordName,String suffix){
System.out.println("啓動Word");
long start = System.currentTimeMillis();
String source = wordPath + wordName + suffix;
target = target + wordName ;
ActiveXComponent app = null;
try {
app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", false);
app.setProperty("DisplayAlerts", new Variant(false));
Dispatch docs = app.getProperty("Documents").toDispatch();
System.out.println("打開文檔" + source);
Dispatch doc = Dispatch.call(docs,//
"Open", //
source,// FileName
false,// ConfirmConversions
true // ReadOnly
).toDispatch();
System.out.println("轉換文檔到PDF " + target);
File tofile = new File(target);
//驗證目標路徑是否存在
if (tofile.exists()) {
System.out.println("存在");
}
Dispatch.call(doc,//
"SaveAs", //
target, // FileName
wdFormatPDF);
Dispatch.call(doc, "Close", false);
long end = System.currentTimeMillis();
System.out.println("轉換完成..用時:" + (end - start) + "ms.");
// Cut.cutfile(str_s,str_d);
} catch (Exception e) {
System.out.println("========Error:文檔轉換失敗:" + e.getMessage());
} finally {
if (app != null)
app.invoke("Quit", wdDoNotSaveChanges);
}
}
public void ppt2pdf(String wordPath,String target,String wordName,String suffix){
System.out.println("啓動PPT");
String source = wordPath + wordName + suffix;
target = target + wordName ;
long start = System.currentTimeMillis();
ActiveXComponent app = null;
try {
app = new ActiveXComponent("Powerpoint.Application");
Dispatch presentations = app.getProperty("Presentations").toDispatch();
System.out.println("打開文檔" + source);
Dispatch presentation = Dispatch.call(presentations,//
"Open",
source,// FileName
true,// ReadOnly
true,// Untitled 指定文件是否有標題。
false // WithWindow 指定文件是否可見。
).toDispatch();
System.out.println("轉換文檔到PDF " + target);
File tofile = new File(target);
if (tofile.exists()) {
tofile.delete();
}
Dispatch.call(presentation,//
"SaveAs", //
target, // FileName
ppSaveAsPDF);
Dispatch.call(presentation, "Close");
long end = System.currentTimeMillis();
System.out.println("轉換完成..用時:" + (end - start) + "ms.");
} catch (Exception e) {
System.out.println("========Error:文檔轉換失敗:" + e.getMessage());
} finally {
if (app != null) app.invoke("Quit");
}
}
}
再定義一個poi轉換Html的一個類ExcelToHtml
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class ExcelToHtml {
private final static ExcelToHtml oOfficeToXML = new ExcelToHtml();
public static ExcelToHtml getInstance() {
return oOfficeToXML;
}
public ExcelToHtml() {
}
/**
* 因爲poi轉換的Html頁面在瀏覽器中顯示時會出現亂碼問題,這裏強制轉換一下
* @param filePath
*/
public void html2utf(String filePath) {
try {
String content = "charset=utf-8";
String templateContent = "";
FileInputStream fileinputstream = new FileInputStream(filePath);// 讀取模板文件
// 下面四行:獲得輸入流的長度,然後建一個該長度的數組,然後把輸入流中的數據以字節的形式讀入到數組中,然後關閉流
int lenght = fileinputstream.available();
byte bytes[] = new byte[lenght];
fileinputstream.read(bytes);
fileinputstream.close();
// 通過使用默認字符集解碼指定的 byte 數組,構造一個新的
//因爲原來的html文件是gb2312格式,所以轉爲string時也要以GBK格式讀取,不然依舊是亂碼
templateContent = new String(bytes, "GBK");
templateContent = templateContent.replaceFirst("charset=gb2312", content);
// 因爲已經替換字符串了,所以使用UTF-8字符集將此 String 編碼爲 byte 序列,並將結果存儲到一個新的 byte 數組中。
byte tag_bytes[] = templateContent.getBytes("UTF-8");
FileOutputStream fileoutputstream = new FileOutputStream(filePath);// 建立文件輸出流
fileoutputstream.write(tag_bytes);
fileoutputstream.close();
} catch (Exception e) {
System.out.print(e.toString());
}
}
public boolean ExceltoHtml(String wordPath,String original_name,String target,String wordName,String suffix) {
ComThread.InitSTA();
ActiveXComponent activexcomponent = new
ActiveXComponent("Excel.Application");
String source = wordPath + original_name + suffix;
target = target + wordName;
boolean flag = false;
try
{
activexcomponent.setProperty("Visible", new Variant(false));
Dispatch dispatch =
activexcomponent.getProperty("Workbooks").toDispatch();
Dispatch dispatch1 = Dispatch.invoke(dispatch, "Open", 1, new
Object[] {
source, new Variant(false), new Variant(true)
}, new int[1]).toDispatch();
Dispatch.call(dispatch1, "SaveAs", target, new Variant(44));
Variant variant = new Variant(false);
Dispatch.call(dispatch1, "Close", variant);
flag = true;
}
catch(Exception exception)
{
System.out.println("|||" + exception.toString());
}
finally
{
activexcomponent.invoke("Quit", new Variant[0]);
ComThread.Release();
ComThread.quitMainSTA();
}
return flag;
}
}
主要的兩個類已完成,因爲這只是一個小demo所以代碼可能有些不太規範
controller類
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import pojo.UpFile;
import tools.ExcelToHtml;
import tools.Word2Pdf;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/sys")
public class controller {
Word2Pdf word2Pdf = new Word2Pdf();
@RequestMapping("/index")
public ModelAndView index(){
ModelAndView modelAndView = new ModelAndView();
// Word2Pdf word2Pdf = new Word2Pdf();
// word2Pdf.word2pdf("G:\\Test\\","G:\\Test\\PDF\\","",".doc");
// modelAndView.setViewName("index");
return modelAndView;
}
@RequestMapping(value="/upload.json",method=RequestMethod.POST)
@ResponseBody
public Map<Object,Object> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
UpFile upFile = new UpFile();
Map<Object,Object> map = new HashMap<Object, Object>();
String suffix = file.getOriginalFilename().substring(
file.getOriginalFilename().lastIndexOf("."));
String fileName = file.getOriginalFilename().substring(0,
file.getOriginalFilename().lastIndexOf("."));
String time = new SimpleDateFormat("yyyyMMddHHmmssSSS") .format(new Date() );
String filePath = request.getSession().getServletContext().getRealPath("upload/");
String target = "G:\\Test_02\\target\\backend\\statics\\pdf\\";
// String FileName = "\\statics\\pdf\\"+fileName+".pdf";
String FileName = "/statics/pdf/"+fileName+".pdf";
// 上傳到/target/backend/upload/的暫存文件夾下
File dir = new File(filePath,fileName+suffix);
file.transferTo(dir);
if (suffix.equals(".doc")||suffix.equals(".docx")){
WordToPdf(filePath,target,fileName,suffix);
} else if (suffix.equals(".ppt")||suffix.equals(".pptx")){
PptToPdf(filePath,target,fileName,suffix);
} else if (suffix.equals(".xls")||suffix.equals(".xlsx")) {
//有些瀏覽器會把html名字中的中文進行編譯,導致404 所以我名字我就用時間戳代替了
//原文件名
String original_name = fileName;
//更改後的名字
String changeName = "Html" + time;
ExcelToHtml(filePath, original_name, changeName, suffix);
FileName = "\\statics\\Html\\" + changeName + ".htm";
}
map.put("filename",FileName);
return map;
}
public void WordToPdf(String filePath,String target,String fileName,String suffix){
word2Pdf.word2pdf(filePath,target,fileName,suffix);
}
public void PptToPdf(String filePath,String target,String wordName,String suffix){
word2Pdf.ppt2pdf(filePath,target,wordName,suffix);
}
public void ExcelToHtml(String filePath,String original_name,String wordName,String suffix){
ExcelToHtml excelToHtml = new ExcelToHtml();
excelToHtml.ExceltoHtml(filePath,original_name,"G:\\Test_02\\target\\backend\\statics\\Html\\",wordName,suffix);
excelToHtml.html2utf("G:\\Test_02\\target\\backend\\statics\\Html\\"+wordName+".htm");
}
}
前臺頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="/statics/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
var filePath = "";
function load(){
if (filePath==""||filePath.length==0){
alert("請先上傳文件");
}
document.getElementById("iframe").src=filePath
}
function test(){
var form = new FormData(document.getElementById("form"));
$.ajax({
url:"/sys/upload.json",
type:"post",
data:form,
cache: false,
processData: false,
contentType: false,
success:function(data){
filePath = (data.filename);
alert("上傳成功");
}, error:function(e){
alert(e.error);
window.clearInterval(timer);
}
})
}
</script>
</head>
<body>
<form class="form" enctype="multipart/form-data" id="form">
選擇文件:<input type="file" name="file" width="180px">
<input type="button" value="上傳" οnclick="test()">
<input type="button" value="預覽" οnclick="load()">
</form>
<iframe src="" id="iframe" width="100%" height="650px"/>
</body>
</html>
總結一下jacob的利弊
優點:相對於其他方法可以較爲完好的轉換。
缺點:轉換效率很低,通常一個Word需要4s左右,大一點的文件就很慢了,不支持跨平臺,只能在windows下運行。