一、OpenOffice服务安装于Windows服务器上的情况;之后会写在Linux的centos7服务器上的情况下使用OpenOffice预览文件
1.了解如何实现如docx、doc、txt、ppt等office格式文件的预览 ?
(1):我们可以知道一般的浏览器都提供了可以直接查看pdf文件的功能,而对于txt、docx等office格式是不支持的,所以为了在不让用户下载文件的情况下快速查看
文件内容,文件的预览功能自然便是比较迫切的了,所以实现预览,无非便是将各类office格式的文件转换为如pdf格式等浏览器可以直接打开的格式文件,然后便可以使用合适的访问方式进行预览即可。
2.如何进行转换格式且预览?
(1):我所采用的是使用开源的软件OpenOffice进行转换,当然还有其他方式,不过目前我采用了这个方式。且看我的前一篇office格式转换为pdf格式文章的链接文章有介绍如何使用进行转换。当然这里我们需要预览的的是一个不确定的文件,并非一个直接固定的文件,所以这里我们还需要稍作修改代码。且看代码如下:
/*
* @param file_id :该变量为在数据库中保存文件信息的主键id,通过该id获取到
* 关于文件在fastdfs中的GroupName以及RemoteFilePath等信息
*
*/
@RequestMapping("/previewfile")
public ResponseEntity<byte[]> previewToPdf(int file_id) throws MyException, IOException {
//1.通过该id获取到该文件信息
EnclosureFile en = enclosureService.getById(file_id);
//2.传递GroupName,及远程路径名RemoteFilePath通过FastDFS相关功能从服务器上下载到相关数据
// 该数据为字节数组类型,若不知FastDFS且翻看我之前的文章即可
byte[] buffFile = FastDFSUtil.download(en.getGroupName(),en.getRemoteFilePath());
//3.现在已经得到需要预览的文件数据,当然我们是不知道其的文件格式的,所以我们可以做个判断
// 若其为pdf或其他非office格式的文件则不转换,直接返回即可
// 而文件格式,我们直接通过存在数据库中的信息获取即可
// 其实文件格式也就是其后缀名,如txt,docx,xls等
String fileType = en.getFileType();
//4.这里做一个判断,其是否为office类型的格式,当然这里我就不写这一步了,我就为了方便就直接
// 默认了格式符合要求,不过通过该文件类型便可以确定出文件名称
// newFileName 为字节数组转换所成文件名称
// pdfName 为后面转换成的pdf文件名称
String newFileName = IdUtil.fastSimpleUUID()+"."+fileType;
String pdfName = IdUtil.fastSimpleUUID()+".pdf";
//5.现在就要翻开我之前写的那篇文章里面的转换方法了,可以发现OpenOffice提供的convert方法
// 的两个参数都是File文件类型,而现在我们得到的是数据为字节数组byte[]
// 故而,我们便可以直接将byte[]类型转换为File类型不就ok了
// 下方的语句,中使用到了byteToFile函数,这个函数我就放在后面了,这里就叙述一下其中
// 函数的参数:1.buffFile为上方得到的字节数组,2.D:"\\OpenOffice"+File.separator :为
// 字节数组转换成文件后的文件夹目录,3.newFileName 为转换后的文件名称
File sourceFile =
OpenOfficeUtil.byteToFile(buffFile,"D:\\OpenOffice"+File.separator,newFileName);
//6.现在已经得到了从字节数组转换而来的文件 sourceFile
// 可以着手开始转换成pdf了,看到下方是否眼熟
// 现在已经得到了convert函数的最重要的两个参数,输入文件与最终的pdf文件
File inputfile = new File("D:\\OpenOffice\\"+newFileName);
File outputfile = new File("D:\\OpenOffice\\"+pdfName);
//7.建立OpenOffice连接,确保OpenOffice服务已经打开
OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1",8100);
try {
connection.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(inputfile,outputfile);
connection.disconnect();
inputfile.delete(); //转换成功记得将之前的文件删除,先保留pdf文件即可
//8.到这里文件已经转换成功,且成功得到了pdf文件,即outputfile
// 而现在得到了pdf文件,但是要如何从vue中进行访问到pdf呢
// 果断出手,将得到的pdf文件果断进行转换成字节数组byte[]进行返回给前端进行访问即可
// 可以看到,下方又出现了一个新方法,为fileToByteArray该函数即为将文件转为字节数组的方法
byte[] pdfByte = OpenOfficeUtil.fileToByteArray(outputfile);
outputfile.delete(); //既然已经得到了字节数组数据,记得将产生的pdf文件进行删除
//9.现在pdf格式的字节数组已经果断拿到,那么接下来便是将其返回给前端,可以看到该Controller
// 方法的返回值格式为 : ResponseEntity<byte[]>
// 这个格式大有可为,直接在前端采用 blob格式便可以果断访问,后面会给出vue的相关代码
// 所以现在果断出手,设置ResponseEntity返回的一些必要准备,如HttpHeaders的设置
// 下方有些HttpHeader不用设置,不过为了保险起见,我便都设置了,其中的
// attachment是设置让浏览器下载的,当然我们是预览,所以不用下载,但是这里设置了
// 也ok,只要前端改一下,不下载就行,但是也不保证有需求,想下载转换了的pdf文件,所以我
// 暂且保留了
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(outputfile.length());
String fileName = URLEncoder.encode(outputfile.getName(),"utf-8");
headers.setContentDispositionFormData("attachment",fileName);
//10.这里便是将相关参数传递到该ResponseEntity中
ResponseEntity<byte[]> responseEntity =
new ResponseEntity<byte[]>(pdfByte,headers,HttpStatus.OK);
return responseEntity; //直接返回即可,若前端配置的有拦截状态码记得使用status===200
}catch (ConnectException e) {
e.printStackTrace();
}
return null; //这里就返回个null即可
}
3.其中用到的两个文件格式转换函数如下:
// 1. 字节数组转换为文件
/*
* 将byte[] 转为 File 文件
* @param: bfile 文件的byte数组 byte[]
* @param: filepath 要写入的文件位置 "D:\\OpenOffice" + File.separator
* @param: filename 写入之后的文件名称如 "xxx.docx"
*
*/
public static File byteToFile(byte[] bfile,String filePath,String fileName)
{
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(filePath); //创建了一个文件目录,若不存在则建立该目录
if(!dir.exists()&&dir.isDirectory()){//判断文件目录是否存在
dir.mkdirs();
}
file = new File(filePath+"\\"+fileName); //创建一个文件,
fos = new FileOutputStream(file); //将
bos = new BufferedOutputStream(fos);
bos.write(bfile); //将字节写入文件中
return file;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return null;
}
// 2. 文件如pdf转换为字节数组
/*
* 将文件转为字节数组
* file change to byte[]
*/
public static byte[] fileToByteArray(File file) throws IOException {
byte[] fileByte = new byte[(int)file.length()];
// FileInputStream是InputStream的子类,用于从文件中读取信息
FileInputStream fis = new FileInputStream(file);
// 利用ByteArrayOutputStream将FileInputStream文件数据读出来
// ByteArrayOutputStream用来在内存中创建缓冲区,所有送往"流"的数据都要放置在此缓冲区
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while((len = fis.read(b)) != -1 ) {
// write(byte[], int off, int len): 写入字节数组b,从b的第off下标开始,写入len个字节
bos.write(b, 0, len);
}
// toByteArray()方法得到文件的字节数组
fileByte = bos.toByteArray();
return fileByte;
}
4.前端vue的相关代码实现:
//预览页面,预览txt,pdf,doc,xls,ppt
// editPage包含了文件id的信息
// 发送axios请求
filePreview(editPage){
this.$axios({
method:'GET',
url:this.dbURL+'/document/previewfile?file_id='+editPage.id,
headers:{"Authorization":localStorage.getItem("token")},
responseType: 'arraybuffer'
//responseType: 'blob'
}).then(res=>{
console.log("excute previewFile ...")
console.log(res)
console.log(res.data)
let a = document.createElement('a');
let blob = new Blob([res.data],{
type:'application/pdf' //也是必不可少的
});
let objectUrl = window.URL.createObjectURL(blob);
window.open(objectUrl) //这一步应该就是其中精髓了
})
},
到此便实现了简洁明了的文件预览功能,主要是要理解其中该功能实现流程便可以一步步将其实现出来,上面代码只是基于windows服务器的简单预览版本。
**********************************************************分割线**********************************************
二、linux系统centos7中使用OpenOffice的预览版本
其实也就是将文件路径稍微设置一下,使用如下代码:将路径分别进行设置一下即可,这样当项目部署于Linux系统上时则同样稳定运行
//filePath是自己规定的,也就是后面pdf文件产生时放在的文件夹路径
//不过这个路径一旦确定,便不应随便更改,且用于删除文件时候
//该文件夹路径也必须保持一致
String filePath = " ";
String osName = System.getProperty("os.name");
if(Pattern.matches("Linux.*",osName))
{ System.out.println("当前处于Linux系统.");
filePath = "/usr/local/TempOpenOffice";
}
else if(Pattern.matches("Windows.*", osName)) {
System.out.println("当前处于Windows系统.");
filePath = "D:\\OpenOfficeTemp";
}
File dir = new File(filePath);
// 判断文件目录是否存在,若不存在则建立OpenOffice文件夹,且是文件夹
if(!dir.exists()){
dir.mkdirs();
//创建了相关文件夹,但若是当前如D盘不存在则换为C盘,linux则不会出现该情况
}
//4.建立好一个输出pdf文件,之后通过OutputStream向该文件写入数据
//File.separatorChar 在windows 为 \\ 在linxu系统为 /
File outputfile = new File(filePath+File.separatorChar+newFilePdfName);