Logo

Logo

Office Online Server搭建(全网最详细)

Pastore Antonio
Pastore Antonio 2022年06月08日
1046 阅读 0 评论 约 14097 字 阅读约 29 分钟

前言

最近换新公司了,一直挺忙的,好久没正儿八经的吹牛逼了!新公司技术部门有定期学习计划,和技术储备计划,这不来了个在线预览文档的活么,作为公司技术储备,需求产生的背景:公司Word、Excel、PDF等文档挺多的,基本上都是展示文件名,然后点击下载到电脑才能查看的这种,不是很方便,那么直接搞成在线预览的可能比较香吧!

正文

本文将是全网最详细的Office Online Server 2016搭建教程,提供服务器版本选择,Windows Server 启动盘制作,Windows服务器搭建,域服务器配置,Windows服务器组网,Office Online Server2016 前置环境搭建、Office Online Server 2016 安装,Wopi服务搭建,以及一些坑的解决!首先需要准备两套服务器,而且都必须是Windows Server 2012 R2版本的服务器,推荐使用下方红框内的ISO镜像,其他版本的安装更新时会报错

实现效果

docx
在这里插入图片描述
xlsx
在这里插入图片描述
ppt
在这里插入图片描述
等其他的格式我这里就不易伊一列出来了!

服务器版本选择

这里版本一定要搞对,不然各种问题,选择windows_server_2012_r2,看到我这里三个不同的Windows Server版本就知道这里版本不对有多少坑了吧,我这里不跟你们说建议用那个版本,你们就用cn_windows_server_2012_r2_vl_with_update_x64_dvd_4051059.iso版本,如果想采坑的自便!
在这里插入图片描述
迅雷下载地址

ed2k://|file|cn_windows_server_2012_r2_vl_with_update_x64_dvd_4051059.iso|4683122688|BD0B95997679F83A4EE2D062865D8E64|/

4个多G,用迅雷下载不慢亲测5分钟!

Windows Server 系统启动盘制作

镜像下载下来后,我们开始制作Windows Server 2016的启动盘制作

启动盘制作工具我们选用U深度装机U深度装机官网

插入U盘

启动U深度装机

选择ISO模式
在这里插入图片描述
选择镜像
在这里插入图片描述
注意镜像千万别搞错了,是这个 cn_windows_server_2012_r2_x64_dvd_2707961.iso

开始制作
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
注意这里选择否,详细问题请见我的往期文章有提到这里为什么不选择是!Linux系统安装

写入镜像
在这里插入图片描述
启动盘最后大小
在这里插入图片描述

Windows Server 系统安装

这个每个电脑主板不同进入方式和安装方式都不同,我这里就以戴尔、麦本本举例吧!

戴尔
开机后长按F12,进入主板,选择USB模式,然后就会进入Windows Server 系统安装引导界面,然后傻瓜式操作点点点就行!

麦本本
开机后长按F2,进入主板,这里和戴尔的有点不同,需要切换启动盘顺序,详细查阅官网吧!这个我怕用文字描述吓到你们。然后就是傻瓜式操作了!

搭建域控服务器

打开服务器管理器,添加角色和功能;
在这里插入图片描述
出现“添加角色和功能”界面,下一步 。
在这里插入图片描述
根据提示操作,下一步。
在这里插入图片描述
根据提示操作,下一步。
在这里插入图片描述
选择添加AD域服务(Active Directory 域服务),同时添加所需功能。
在这里插入图片描述
根据提示操作,下一步
在这里插入图片描述
安装完成 。
在这里插入图片描述
配置域
点击服务器管理器左侧“AD DS” 、点击黄色提示部分中的更多。
在这里插入图片描述
点击“将此服务器升级为域控制器” 。
在这里插入图片描述
进入AD域服务器配置向导,选择 “添加新林” ,输入域,点击下一步。
在这里插入图片描述

域填写这个,contoso.com不要问我为什么,照着弄就行!

填写密码,下一步 。
在这里插入图片描述
注意一下,这里两台服务器密码最好保持一致,服务器时间要校准
提示DNS无法创建,不用管,继续下一步 。
在这里插入图片描述
安装路径,默认,下一步 。
在这里插入图片描述
查看选项,默认,下一步 。

在这里插入图片描述
点击安装 。此过程可能会报错,提示登陆用户没有设置密码,去设置给当前登陆用户(Administrator)设置一个密码,然后回来点击 “重新运行先决条件检查” 即可!
在这里插入图片描述
安装完成,会提示注销重启 (此过程比较漫长,耐心等待)。
在这里插入图片描述

Windows服务器组网

打开转换服务器,修改转换服务器的NDS,指向域控服务器(刚才的服务器ip地址)。
在这里插入图片描述
在计算机属性中,修改计算机名称(随意),并添加到域控服务器(域为“添加新林”时设置的域名),确定后提示注销重启服务器。

在这里插入图片描述
打开域控服务器,点击管理 > 添加服务器,输入转换服务器修改后的计算机名称,立即查找。将搜索到的服务器双击添加到右边,点击确定。
在这里插入图片描述
在这里插入图片描述
在域控服务器中,所有服务器显示两台服务器,并都是联机状态则表示成功 。
在这里插入图片描述

Office Online Server2016 前置环境搭建

Office Online Server 官网
知道你们不喜欢看官网,那就为难一下我搬运一下官网吧!不过微软的门户做的挺好的,尤其是下载软件的通道,但是他们注册的渠道是真TM恶心,机器人验证的时候简直就是智障,不信你们可以体验一下!

以管理员身份打开 Microsoft PowerShell 提示符,然后运行此命令示例来安装必需的角色和服务。

Add-WindowsFeature Web-Server,Web-Mgmt-Tools,Web-Mgmt-Console,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Static-Content,Web-Performance,Web-Stat-Compression,Web-Dyn-Compression,Web-Security,Web-Filtering,Web-Windows-Auth,Web-App-Dev,Web-Net-Ext45,Web-Asp-Net45,Web-ISAPI-Ext,Web-ISAPI-Filter,Web-Includes,InkandHandwritingServices,NET-Framework-Features,NET-Framework-Core,NET-HTTP-Activation,NET-Non-HTTP-Activ,NET-WCF-HTTP-Activation45,Windows-Identity-Foundation,Server-Media-Foundation

在这里插入图片描述
在这里插入图片描述
安装完成后重启。

NET Framework 4.5.2
在这里插入图片描述
点击下载即可,后面几个环节都是!顺序不能错哦!

Visual C++ Redistributable Packages for Visual Studio 2013

Visual C++ Redistributable for Visual Studio 2015

Microsoft.IdentityModel.Extention.dll

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Office Online Server 2016 安装

Office Online Server 2016这个安装包还挺难找的,如果从官网上下在,那就会碰到那个智障机器人检验,注册入口我放着,有想体验的自己可以试试!访问批量许可服务中心

百度网盘下载密码: guc8Office Online Server 2016
在这里插入图片描述
解压
在这里插入图片描述
再解压n-moos16.rar得到n-moos16.iso
在这里插入图片描述

下面进入主题了,安装office online。
双击下载好的office online 安装包,进行安装。
在这里插入图片描述
安装成功。
在这里插入图片描述
安装语言包。

在这里插入图片描述
安装成功。
在这里插入图片描述
启动office Online 服务器场

打开安装office Online 的主机,打开powerShell。

Import-Module OfficeWebApps

部署服务器场:

New-OfficeWebAppsFarm -InternalURL “http://officeserver.contoso.com” -ExternalUrl “http://192.168.1.24-AllowHttpEditingEnabled

-InternalURL:内网浏览地址,http://xx.domin.com 其中 xx表示计算机名 domin.com 表示域名 也可以设置为对应的IP地址
-ExternalURL:外网浏览地址
-AllowHttp: 允许80端口访问
-OpenFromUrlEnabled:允许通过url方式进行预览
-CacheLocation: 缓存文件存放路径 默认是C:\ProgramData\Microsoft\OfficeWebApps\Working\d
-CacheSizeInGB: 最大缓存文件大小 单位GB 默认为15GB

在这里插入图片描述

关闭两台服务器防火墙
访问http:// 192.168.1.24/hosting/discovery 测试是否启动
在这里插入图片描述
若http:// 192.168.1.24/hosting/discovery 能登录,http://192.168.1.24/op/generate.aspx显示“服务器错误”,控制台输入Set-OfficeWebAppsFarm -OpenFromUrlEnabled:$true即可访问成功

访问http://officeserver.contoso.com/op/generate.aspx测试 http://officeserver.contoso.com为officeserver地址
在这里插入图片描述
ok

Wopi服务搭建

上代码吧,做点程序员该干的活吧!

使用SpringBoot脚手架创建一个web工程

FileInfo

package com.tao.wopihost.entity;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.io.Serializable;

/**
 * @author TAO
 * @description: TODO
 * @date 2021/6/26 20:48
 */
public class FileInfo implements Serializable {

    /**
     * 必须字段
     */
    // 包含扩展的文件名
    @JsonProperty("BaseFileName")
    private String baseFileName;
    // 文件大小(单位:byte)
    @JsonProperty("Size")
    private long size;
    // 唯一标识文件所有者
    @JsonProperty("OwnerId")
    private String ownerId;
    // 文件版本号,文件如果被编辑,版本号也要跟着改变
    @JsonProperty("Version")
    private long version;
    // SHA-2 256位散列编码值(获取该文件的文件流->SHA256计算文件流Hash值->将Hash值转换为Base64String)
    @JsonProperty("SHA256")
    private String sha256;

    /**
     * 编辑时可能用到的字段
     */
    // 是否允许连接到文件中引用的外部服务(例如,可嵌入javascript应用程序)
    @JsonProperty("AllowExternalMarketplace")
    private boolean allowExternalMarketplace = true;
    // 是否有权限修改
    @JsonProperty("UserCanWrite")
    private boolean userCanWrite = true;
    // 是否支持更新
    @JsonProperty("SupportsUpdate")
    private boolean supportsUpdate = true;
    // 是否支持锁定
    @JsonProperty("SupportsLocks")
    private boolean supportsLocks = true;

    /**
     * 其他字段
     */
    // 是否支持使用WOPI客户端创建新文件
    private boolean SupportsFileCreation = true;
    // 是否支持用户可以通过受限制的URL以有限的方式对文件进行操作的方案
    private boolean SupportsScenarioLinks = true;

    public String getBaseFileName() {
        return baseFileName;
    }

    public void setBaseFileName(String baseFileName) {
        this.baseFileName = baseFileName;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public String getOwnerId() {
        return ownerId;
    }

    public void setOwnerId(String ownerId) {
        this.ownerId = ownerId;
    }

    public long getVersion() {
        return version;
    }

    public void setVersion(long version) {
        this.version = version;
    }

    public String getSha256() {
        return sha256;
    }

    public void setSha256(String sha256) {
        this.sha256 = sha256;
    }

    public boolean isAllowExternalMarketplace() {
        return allowExternalMarketplace;
    }

    public void setAllowExternalMarketplace(boolean allowExternalMarketplace) {
        this.allowExternalMarketplace = allowExternalMarketplace;
    }

    public boolean isUserCanWrite() {
        return userCanWrite;
    }

    public void setUserCanWrite(boolean userCanWrite) {
        this.userCanWrite = userCanWrite;
    }

    public boolean isSupportsUpdate() {
        return supportsUpdate;
    }

    public void setSupportsUpdate(boolean supportsUpdate) {
        this.supportsUpdate = supportsUpdate;
    }

    public boolean isSupportsLocks() {
        return supportsLocks;
    }

    public void setSupportsLocks(boolean supportsLocks) {
        this.supportsLocks = supportsLocks;
    }

    public boolean isSupportsFileCreation() {
        return SupportsFileCreation;
    }

    public void setSupportsFileCreation(boolean supportsFileCreation) {
        SupportsFileCreation = supportsFileCreation;
    }

    public boolean isSupportsScenarioLinks() {
        return SupportsScenarioLinks;
    }

    public void setSupportsScenarioLinks(boolean supportsScenarioLinks) {
        SupportsScenarioLinks = supportsScenarioLinks;
    }
}

注意属性名称大写转一下!

WopiHostContrller

package com.tao.wopihost.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tao.wopihost.entity.FileInfo;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
 * @author TAO
 * @description: WOPI HOST
 * @date 2021/6/26 20:48
 */
@RestController
@RequestMapping(value = "/wopi")
public class WopiHostContrller {

    @Value("${file.path}")
    private String filePath;

    /**
     * 获取文件流
     *
     * @param name
     * @param response
     */
    @GetMapping("/files/{name}/contents")
    public void getFile(@PathVariable(name = "name") String name, HttpServletResponse response) {
        System.out.println("GET获取文件啦!!!!");
        InputStream fis = null;
        OutputStream toClient = null;
        try {
            // 文件的路径
            String path = filePath + name;
            File file = new File(path);
            // 取得文件名
            String filename = file.getName();
            // 以流的形式下载文件
            fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            // 清空response
            response.reset();

            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" +
                    new String(filename.getBytes("utf-8"), "ISO-8859-1"));
            response.addHeader("Content-Length", "" + file.length());
            toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            System.out.println("GET获取文件Contents结束!!!!");

        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                fis.close();
                toClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 保存更新文件
     *
     * @param name
     * @param content
     */
    @PostMapping("/files/{name}/contents")
    public void postFile(@PathVariable(name = "name") String name, @RequestBody byte[] content) {
        System.out.println("POST获取文件Contents啦!!!!");
        // 文件的路径
        String path = filePath + name;
        File file = new File(path);
        FileOutputStream fop = null;
        try {
            if (!file.exists()) {
                file.createNewFile();//构建文件
            }
            fop = new FileOutputStream(file);
            fop.write(content);
            fop.flush();
            System.out.println("POST获取文件结束!!!!");

            System.out.println("------------ save file ------------ ");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fop.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取文件信息
     *
     * @param request
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    @GetMapping("/files/{name}")
    public void getFileInfo(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("获取文件啦!!!!");
        String uri = request.getRequestURI();
        FileInfo info = new FileInfo();
        try {
            // 获取文件名, 防止中文文件名乱码
            String fileName = URLDecoder.decode(uri.substring(uri.indexOf("wopi/files/") + 11, uri.length()), "UTF-8");
            if (fileName != null && fileName.length() > 0) {
                System.out.println("文件不为空啊");
                File file = new File(filePath + fileName);
                if (file.exists()) {
                    // 取得文件名
                    info.setBaseFileName(file.getName());
                    info.setSize(file.length());
                    info.setOwnerId("admin");
                    info.setVersion(file.lastModified());
                    info.setSha256(getHash256(file));
                    info.setAllowExternalMarketplace(true);
                    info.setUserCanWrite(true);
                    info.setSupportsUpdate(true);
                    info.setSupportsLocks(true);
                }
            }

            ObjectMapper mapper = new ObjectMapper();
            String Json = mapper.writeValueAsString(info);

            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(Json);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取文件的SHA-256值
     *
     * @param file
     * @return
     */
    public static String getHash256(File file) {
        String value = "";
        // 获取hash值
        try {
            byte[] buffer = new byte[1024];
            int numRead;
            InputStream fis = new FileInputStream(file);
            //如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256
            MessageDigest complete = MessageDigest.getInstance("SHA-256");
            do {
                //从文件读到buffer
                numRead = fis.read(buffer);
                if (numRead > 0) {
                    //用读到的字节进行MD5的计算,第二个参数是偏移量
                    complete.update(buffer, 0, numRead);
                }
            } while (numRead != -1);

            fis.close();
            value = new String(Base64.encodeBase64(complete.digest()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return value;
    }

}

application.yml

server:
  port: 80


file:
  path: E:\file\

path是域服务器上文件存放位置
打包

在这里插入图片描述
放到域服务器上运行!
在这里插入图片描述
创建测试文档
在这里插入图片描述
注意这里两台服务器需要互相能ping通,

文档地址配置
1.由于微软这款软件对IP有访问限制,所以需将IP转化为域名进行访问,所以需要进行配置,来让软件自动进行域名转化为IP,具体路径如下

在这里插入图片描述

192.168.1.24 officeserver.contoso.com
192.168.1.16 contoso.com

完整性测试

docx
http://officeserver.contoso.com/op/view.aspx?src=http://contoso.com/wopi/files/test1.docx/contents
在这里插入图片描述
xlsx
http://officeserver.contoso.com/op/view.aspx?src=http://contoso.com/wopi/files/test3.xlsx/contents
在这里插入图片描述
ppt
http://officeserver.contoso.com/op/view.aspx?src=http://contoso.com/wopi/files/111.ppt/contents在这里插入图片描述

搞定,睡了睡了。

查看完整代码

橙子主题打折出售

其实我不卖,主要是这里是放广告的,所以就放了一个
毕竟主题都没做完,卖了也是坑.

购买它

附件下载

共 56 个文件
在这里插入图片描述
PNG 443.7 KB
在这里插入图片描述
PNG 61.4 KB
在这里插入图片描述
PNG 549.2 KB
在这里插入图片描述
PNG 178.5 KB
在这里插入图片描述
PNG 3.1 MB
在这里插入图片描述
PNG 2.5 MB
在这里插入图片描述
PNG 3.1 MB
在这里插入图片描述
PNG 3.1 MB
在这里插入图片描述
PNG 3.0 MB
在这里插入图片描述
PNG 3.3 MB
在这里插入图片描述
PNG 1.9 MB
在这里插入图片描述
PNG 179.8 KB
在这里插入图片描述
PNG 171.2 KB
在这里插入图片描述
PNG 129.7 KB
在这里插入图片描述
PNG 164.9 KB
在这里插入图片描述
PNG 265.9 KB
在这里插入图片描述
PNG 154.3 KB
在这里插入图片描述
PNG 169.3 KB
在这里插入图片描述
PNG 161.1 KB
在这里插入图片描述
PNG 95.6 KB
在这里插入图片描述
PNG 124.8 KB
在这里插入图片描述
PNG 142.5 KB
在这里插入图片描述
PNG 119.0 KB
在这里插入图片描述
PNG 121.4 KB
在这里插入图片描述
PNG 176.4 KB
在这里插入图片描述
PNG 326.0 KB
在这里插入图片描述
PNG 164.7 KB
在这里插入图片描述
PNG 243.2 KB
在这里插入图片描述
PNG 229.6 KB
在这里插入图片描述
PNG 116.0 KB
在这里插入图片描述
PNG 73.0 KB
在这里插入图片描述
PNG 120.9 KB
在这里插入图片描述
PNG 37.4 KB
在这里插入图片描述
PNG 91.7 KB
在这里插入图片描述
PNG 200.2 KB
在这里插入图片描述
PNG 53.8 KB
在这里插入图片描述
PNG 30.0 KB
在这里插入图片描述
PNG 35.5 KB
在这里插入图片描述
PNG 54.1 KB
在这里插入图片描述
PNG 3.8 MB
在这里插入图片描述
PNG 1.9 MB
在这里插入图片描述
PNG 1.9 MB
在这里插入图片描述
PNG 85.0 KB
在这里插入图片描述
PNG 33.3 KB
在这里插入图片描述
PNG 68.5 KB
在这里插入图片描述
PNG 39.6 KB
在这里插入图片描述
PNG 200.2 KB
在这里插入图片描述
PNG 355.0 KB
在这里插入图片描述
PNG 153.9 KB
在这里插入图片描述
PNG 105.9 KB
在这里插入图片描述
PNG 430.9 KB
在这里插入图片描述
PNG 490.9 KB
在这里插入图片描述
PNG 33.2 KB
在这里插入图片描述
PNG 677.9 KB
在这里插入图片描述
PNG 106.0 KB
在这里插入图片描述
PNG 572.2 KB
部分文章可能存在转载,如果涉及到侵权,请联系删除文章。

探索AIGC相关的精彩内容,共 15 篇文章

Azure AI 服务之语音识别

简介 Azure AI 服务中的语音识别 API 是微软提供的一项先进技术,旨在帮助开发者轻松实现语 ... Office Online Server搭建(全网最详细)

2026-02-17 · Xzavier Aaron
MCP | 一文详解什么是 MCP以及 MCP 可以做什么

一、什么是 MCP MCP(Model Context Protocol)是一个专为大型语言模型(L ... Office Online Server搭建(全网最详细)

2026-02-14 · Shen, Luke
你的工作流程,值得一个“全自动数字分身”:录制、截图、成文,一气呵成

一、一句话认识 TestFlow Recorder 在数字化工作环境中,如何准确记录操作步骤并生成清 ... Office Online Server搭建(全网最详细)

2026-02-14 · Xzavier Aaron
Flowise 前端框架配置指南

用户需求 问题:有没有适合配置 Flowise 的前端框架? 目标:寻找类似 Open WebUI ... Office Online Server搭建(全网最详细)

2026-02-14 · Xzavier Aaron