前后端分离的SSM项目实现OpenOffice与FastDFS的结合,通过Vue预览附件

一、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);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值