• office web apps 整合到自己项目中(wopi实现在线预览编辑)


    借助office web apps实现在线预览和在线编辑

    我所有的代码都是用go语言编写,你可以直接编译后使用,不用再有其他的操作。
    最近项目实在太忙,这几天才有时间,这次是重头戏,要好好琢磨一下怎么写,才能更简洁的说清楚一切。
    上一节,我们已经安装完毕,安装好了office web apps。大家只要打开浏览器,访问自己的域地址,我的是app.datrix3.com,如果可以看见这个界面

    那就说明你安装无问题了。接下来就要通过Wopi协议将OWA集成到自己的项目中了。

    实现在线预览和编辑的Wopi协议

    首先你要明白什么是wopi协议,相关的资料中,WOPI的全称是“Web Application Open PlatformInterface”,中文名为“Web应用程序开放平台接口协议”。
    要知道,office web apps 可不会允许你直接去调用它相关的接口,网上的一张图就很好的说明了这点:

    你可以看见,在WOPI中,存在WOPI Server(或者称之为WOPI Host)和WOPI Client两种角色,我们可以将WOPI-Client看作我们搭建的OWA服务器,
    而WOPI Server就是我们要自己开发的Wopi服务,在图里可以看见,WOPI Client共向WOPI Server进行了两次请求,分别是Tell me about the file以及Give me the file,所以如果需要实现最简单的在线预览,你需要提供两个接口,如果要实现在线编辑,你还需要一个写入保存的接口。

    第一个接口为:Tell me about the file,我将它定义为GetFileInfo,它的url为
    http://{你自己的owa地址}/api/wopi/files/{file_name}
    这里需要你以JSON形式OWA传参,参数至少要包括如下信息:

    {  
      "BaseFileName": "Sample Document.docx",  
      "OwnerId": "tylerbutler",  
      "Size": 300519,  
      "SHA256":"+17lwXXN0TMwtVJVs4Ll+gDHEIO06l+hXK6zWTUiYms=",  
      "Version":"GIYDCMRNGEYC2MJREAZDCORQGA5DKNZOGIZTQMBQGAVTAMB2GAYA===="  
      }  
    

    BaseFileName: 文件名。
    OwnerId: 文件所有者的唯一编号。
    Size: 文件大小,以bytes为单位。
    SHA256: 文件的256位bit的SHA-2编码散列内容。(Wordweb app必有,excel和ppt可以为null)
    Version: 文件版本号,文件如果被编辑,版本号也要跟着改变。
    下面是我的参数:

    type fileInfo struct {
    	BaseFileName   string `json:"BaseFileName"`
    	OwnerId        string `json:"OwnerId"`
    	Size           int64  `json:"Size"`
    	SHA256         string `json:"SHA256"`
    	Version        string `json:"Version"`
    	SupportsUpdate bool   `json:"SupportsUpdate,omitempty"`
    	UserCanWrite   bool   `json:"UserCanWrite,omitempty"`
    	SupportsLocks  bool   `json:"SupportsLocks,omitempty"`
    }
    

    你可以看见,这里有文件的size,sha256,这里要用代码去获取:

    //获取单个文件的大小
    func getSize(path string) int64 {
    	fileInfo, err := os.Stat(path)
    	if err != nil {
    		panic(err)
    	}
    	fileSize := fileInfo.Size()
    	return fileSize
    }
    
    //获取sha256
    func SHA256File(path string) (string, error) {
    	buf, err := ioutil.ReadFile(path)
    	if err != nil {
    		return "", err
    	}
    	h := sha256.Sum256(buf)
    	return base64.StdEncoding.EncodeToString(h[:]), nil
    }
    

    GetFileInfo接口代码:

    func GetFileInfo(w http.ResponseWriter, r *http.Request) {
    	log.Println("GetFileInfo")
    
    	vals := r.URL.Query()
    	tmp, ok := vals["access_token"]
    	if !ok || len(tmp[0]) == 0 {
    		log.Println("access_token not found!")
    	}
    
    	vars := mux.Vars(r)
    	fileName := vars["file_name"]
    	if len(fileName) == 0 {
    		log.Println("file_name empty!")
    	}
    	log.Println("file_name: ", fileName)
    
    	testFilePath := path.Join(".", fileName)
    
    	log.Println("PATH: ", testFilePath)
    
    	var info fileInfo
    	info.BaseFileName = fileName
    	info.OwnerId = "admin"
    	info.Size = getSize(testFilePath)
    	info.SHA256, _ = SHA256File(testFilePath)
    	log.Println("debug: sha256_b42: ", info.SHA256)
    	// String value: eIMevgBhTd8Iqh1VjWbfWx7wd5vQvmDxlABMfz+pTiI=
    	//info.SHA256 = "eIMevgBhTd8Iqh1VjWbfWx7wd5vQvmDxlABMfz+pTiI="
    
    	info.Version = "2222"
    	info.UserCanWrite = true
    	info.SupportsLocks = true
    
    	w.Header().Set("Content-Type", "application/json")
    
    	json.NewEncoder(w).Encode(info)
    
    	log.Println("GetFileInfo done...")
    }
    

    接下来是第二个接口Give me the file,我将它定义为GetFileContent,用于WOPI Client获取文件,这个接口的url为:
    http://owa服务器地址/api/wopi/files/{file_name}/contents
    这个接口通过文件流的方式返回文件,代码如下

    func GetFileContent(w http.ResponseWriter, r *http.Request) {
    	log.Println("GetFileContent start.......")
    
    	vals := r.URL.Query()
    	tmp, ok := vals["access_token"]
    	if !ok || len(tmp[0]) == 0 {
    		log.Println("access_token not found!")
    	}
    
    	vars := mux.Vars(r)
    	fileName := vars["file_name"]
    	if len(fileName) == 0 {
    		log.Println("file_name empty!")
    	}
    	log.Println("file_name: ", fileName)
    
    	testFilePath := path.Join(".", fileName)
    
    	data, err := ioutil.ReadFile(testFilePath)
    	if err != nil {
    		log.Println("read file err: ", err)
    		return
    	}
    
    	w.Header().Set("Content-type", "application/octet-stream")
    	w.Write(data)
    	//json.NewEncoder(w).Encode(info)
    	log.Println("GetFileContent done !")
    }
    

    如果你需要实现编辑的功能,你需要实现一个上传接口POSTfile,这个接口和上面那个url除了请求方式不同,其他都是一样的。
    http://owa服务器地址/api/wopi/files/{file_name}/contents
    代码如下

    func PostFileContent(w http.ResponseWriter, r *http.Request) {
    	log.Println("PostFileContent start..........")
    
    	vals := r.URL.Query()
    	tmp, ok := vals["access_token"]
    	if !ok || len(tmp[0]) == 0 {
    		log.Println("access_token not found!")
    	}
    
    	vars := mux.Vars(r)
    
    	fileName := vars["file_name"]
    
    	if len(fileName) == 0 {
    		log.Println("file_name empty!")
    	}
    
    	log.Println("file_name: ", fileName)
    
    	testFilePath := path.Join(".", fileName)
    
    	log.Println("PATH: ", testFilePath)
    
    	body, err := ioutil.ReadAll(r.Body)
    
    	if err != nil {
    		log.Println("body empty")
    	}
    
    	ioutil.WriteFile(testFilePath, body, os.ModeAppend)
    
    	w.Header().Set("Content-type", "application/octet-stream")
    
    	// get Path,get file
    
    }
    

    现在三个接口都已经实现了,我们来看一下路由和具体的实现代码:

    func main() {
    
    	router := mux.NewRouter()
    	router.HandleFunc("/api/wopi/files/{file_name}", GetFileInfo).Methods(http.MethodGet)
    	router.HandleFunc("/api/wopi/files/{file_name}/contents", GetFileContent).Methods(http.MethodGet)
    	router.HandleFunc("/api/wopi/files/{file_name}/contents", PostFileContent).Methods(http.MethodPost)
        //开启8080端口
    	err := http.ListenAndServe(":8080", router)
    	log.Println(router)
    	if err != nil {
    		log.Println("http listen err: ", err)
    	}
    }
    

    接下来你就可以go build,然后跑服务了,我这里设置的文件路径都是本目录下的,也就是说,服务在test文件夹下跑起来,那么你的office文件也要放在test文件夹下。

    最后,跑起来服务,应该访问的url如下:

    http://owa服务器地址/we/WordEditorFrame.aspx?WOPISrc=http//本地ip:8080/api/wopi/files/1.docx
    
    http:/owa服务器地址/p/PowerPointFrame.aspx?PowerPointView=ReadingView&WOPISrc=http//本地ip:8080/api/wopi/files/1.pptx
    
    http://owa服务器地址/x/_layouts/xlviewerinternal.aspx?WOPISrc=http//本地ip:8080/api/wopi/files/1.xlsx
    
  • 相关阅读:
    Vim内直接使用p粘贴系统剪切板
    购买主机时的常见宽带类型或运营商
    Bilibli文章无法复制文字
    Python_tkinter(1)_窗口创建与布局
    模拟器中安装APK报Error:INSTALL_FAILED_NO_MATCHING_ABIS
    Fiddler_内置命令行_03
    【摘】Fiddler工具使用介绍
    get和post区别
    jmeter_上一请求的响应值作为下一请求的参数
    jmeter_用户并发登录
  • 原文地址:https://www.cnblogs.com/Yemilice/p/8276664.html
Copyright © 2020-2023  润新知