[Office Web Apps]实现在线office文档预览

摘要

在使用office web apps实现office文档在线预览的时候,需要注意的地方。

web api

web api作为owa在线预览服务回调的接口,这里面核心代码片段如下:

using H5.Business;
using H5.Business.Log;
using H5.Enums;
using H5.Model;
using H5.Utility;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Hosting;
using System.Web.Http;
using WebSite.OfficeViewerService.Helpers;

namespace WebSite.OfficeViewerService.Controllers.Api
{

    [RoutePrefix("api/wopi")]
    public class FilesController : ApiController
    {
        IFileHelper _fileHelper;
        HttpResponseMessage _response;
        ILog _log;
        /// <summary>
        /// Base constructor
        /// </summary>
        public FilesController()
        {
            _fileHelper = new FileHelper();
            _response = new HttpResponseMessage(HttpStatusCode.OK);
            _log = new DbLog(LogSource.WebLog, AppNameType.office_view);

        }
        /// <summary>
        /// Required for WOPI interface - on initial view
        /// </summary>
        /// <param name="name">file name</param>
        /// <returns></returns>        
        [HttpGet]
        [Route("files/{name}")]
        public CheckFileInfo Get(string name)
        {
            _log.Info(new LogModel { Content = "get fileinfo by name", Op = "get_fileinfo" });
            return _fileHelper.GetFileInfo(name);
        }

        /// <summary>
        /// Required for WOPI interface - on initial view
        /// </summary>
        /// <param name="name">file name</param>
        /// <param name="access_token">token that WOPI server will know</param>
        /// <returns></returns>
        [HttpGet]
        [Route("files/{name}")]
        public CheckFileInfo Get(string name, string access_token)
        {
            _log.Info(new LogModel { Content = "get fileinfo by name&access_token", Op = "get_fileinfo" });
            return _fileHelper.GetFileInfo(name);
        }



        /// <summary>
        /// Required for View WOPI interface - returns stream of document.
        /// </summary>
        /// <param name="name">file name</param>
        /// <param name="access_token">token that WOPI server will know</param>
        /// <returns></returns>
        [HttpGet]
        [Route("files/{name}/contents")]
        public HttpResponseMessage GetFile(string name, string access_token)
        {
            _log.Info(new LogModel { Content = "get file contents by name&access_token", Op = "get_fileinfo" });
            return DownLoadFileStream(name, access_token);
        }
        /// <summary>
        /// get owa file
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("files/{name}/contents")]
        public HttpResponseMessage GetFile(string name)
        {
            _log.Info(new LogModel { Content = "get file contents by name", Op = "get_fileinfo" });
            return DownLoadFileStream(name, string.Empty);
        }
        private HttpResponseMessage DownLoadFileStream(string name, string access_token)
        {
            try
            {
                _log.InfoAsync(new LogModel { Content = name + "_" + access_token, Itcode = string.Empty,
Op = "Office_View_GetFile" }); FastDFSFileBusiness fastDFSFileBusiness = new FastDFSFileBusiness(); var file = fastDFSFileBusiness.FindFastDFSFileByMD5(name); if (file != null) { using (WebClient webClient = new WebClient()) { byte[] buffer = webClient.DownloadData(file.Url); _log.Info(new LogModel { Content = "download file success", Op = "get_fileinfo" }); MemoryStream stream = new MemoryStream(buffer); _response.Content = new StreamContent(stream); _response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); } } return _response; } catch (Exception ex) { _log.Error(new LogModel { Ex = ex, Op = "Office_View_GetFile_err" }); _response.StatusCode = HttpStatusCode.InternalServerError; var stream = new MemoryStream(UTF8Encoding.Default.GetBytes(ex.Message ?? "")); _response.Content = new StreamContent(stream); return _response; } } } }

需要注意:在获取文件流的时候,不要是否文件流,不然会造成有的文件预览正常,有的预览报错。

fileHelper用来获取文件信息,这里文件统一上传到文件服务器fastdfs上,通过下载文件流设置文件信息,在传递文件的时候,使用文件md5进行传递,避免因为文件名出现中文名或者空格造成编码问题。

构造owa预览地址

using H5.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Xml.Serialization;

namespace WebSite.OfficeViewerService.Helpers
{
    /// <summary>
    /// 
    /// </summary>
    public class WopiAppHelper
    {
        public WopiAppHelper() { }
        /// <summary>
        /// 获取office在线预览的链接
        /// </summary>
        /// <param name="fileMD5"></param>
        /// <param name="ext"></param>
        /// <param name="fileUrl"></param>
        /// <returns></returns>
        public string GetDocumentLink(string fileMD5, string ext, string fileUrl)
        {
            string apiUrl = string.Format(ConfigManager.OWA_MY_VIEW_URL, fileMD5);
            string findUrl = FindUrlByExtenstion(ext);
            if (!string.IsNullOrEmpty(findUrl))
            {
                return string.Format("{0}{1}{2}&access_token={3}", ConfigManager.OWA_URL, findUrl, apiUrl, fileMD5);
            }
            else
            {
                return fileUrl;
            }

        }
        /// <summary>
        /// 根据文件扩展名获取预览url
        /// </summary>
        /// <param name="ext"></param>
        /// <returns></returns>
        private string FindUrlByExtenstion(string ext)
        {       
            if (string.IsNullOrEmpty(ext))
            {
                throw new ArgumentNullException("extension is empty.");
            }
            if (ext.IndexOf(".") >= 0)
            {
                //如果包含.则进行过滤
                ext = ext.TrimStart('.').ToLower();
            }
            string url = string.Empty;
            switch (ext)
            {
                case "ods":
                case "xls":
                case "xlsb":
                case "xlsm":
                case "xlsx":
                    url = "/x/_layouts/xlviewerinternal.aspx?WOPISrc=";
                    break;
                case "one":
                case "onetoc2":
                    url = "/o/onenoteframe.aspx?WOPISrc=";
                    break;
                case "odp":
                case "pot":
                case "potm":
                case "potx":
                case "pps":
                case "ppsm":              
                case "ppsx":
                case "ppt":
                case "pptm":
                case "pptx":
                    url = "/p/PowerPointFrame.aspx?WOPISrc=";
                    break;
                case "doc":
                case "docm":
                case "docx":
                case "dot":
                case "dotm":
                case "dotx":
                    url = "/wv/wordviewerframe.aspx?WOPISrc=";
                    break;
                default:
                    break;
            }
            return url;
        }
    }
}

总结

在开发中因为涉及到回调,最好找一个代理的工具,比如ngrok将机器代理到外网,方便调试开发。

posted @ 2017-10-31 16:10  wolfy  阅读(3795)  评论(0编辑  收藏  举报