web office apps 在線預覽實踐

摘要

在一些項目中須要在線預覽office文檔,包括word,excel,ppt等。達到預覽文檔的目的有不少方法,能夠看我以前總結,在線預覽的n種方案:html

[Asp.net]常見word,excel,ppt,pdf在線預覽方案,有圖有真相,總有一款適合你!web

,因爲客戶那裏有安裝web office apps服務,調用該服務就能夠實現文檔的在線預覽,因此在項目中就採用了這種方式,下面列出了實踐步驟。數據庫

步驟

定義文件信息:api

 該信息用來調用web office apps服務回調查找文件信息時用到。跨域

    public class CheckFileInfo
    {
        public CheckFileInfo();

        public string BaseFileName { get; set; }
        public string OwnerId { get; set; }
        public long Size { get; set; }
        public string SHA256 { get; set; }
        public string Version { get; set; }
    }

獲取文件信息的接口服務器

    public interface IFileHelper
    {
        Task<CheckFileInfo> GetFileInfo(string fileMD5);
        Task<string> GetSHA256Async(string url);
        string GetSHA256Async(byte[] buffer);
    }

接口實現app

   public class FileHelper : IFileHelper
    {
        FileBusiness _FileBusiness;
        public FileHelper()
        {
            _FileBusiness = new FileBusiness();
        }
        /// <summary>
        /// 獲取文件信息
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public async Task<CheckFileInfo> GetFileInfo(string fileMD5)
        {
            var fileInfo = _FileBusiness.FindFileByMD5(fileMD5);
            if (fileInfo != null)
            {
                var rv = new CheckFileInfo
                {
                    Version = DateTime.Now.ToString("s"),
                    Size = Convert.ToInt64(fileInfo.FileSize),
                    OwnerId = fileInfo.Itcode,
                    BaseFileName = fileInfo.FileName,
                    SHA256 = fileInfo.SHA256
                };
                if (string.IsNullOrEmpty(fileInfo.SHA256))
                {
                    rv.SHA256 = await GetSHA256Async(fileInfo.Url);
                    fileInfo.SHA256 = rv.SHA256;
                    await _FileBusiness.UpldateAsyncByUrl(fileInfo);
                }
                return rv;
            }
            else
            {
                return null;
            }
        }
        public async Task<string> GetSHA256Async(string url)
        {
            string sha256 = string.Empty;
            using (var sha = SHA256.Create())
            {
                WebClient webClient = new WebClient();
                byte[] buffer = await webClient.DownloadDataTaskAsync(url);
                byte[] checksum = sha.ComputeHash(buffer);
                sha256 = Convert.ToBase64String(checksum);
            }
            return sha256;
        }


        public string GetSHA256Async(byte[] buffer)
        {
            string sha256 = string.Empty;
            using (var sha = SHA256.Create())
            {
                WebClient webClient = new WebClient();
                byte[] checksum = sha.ComputeHash(buffer);
                sha256 = Convert.ToBase64String(checksum);
            }
            return sha256;
        }
    }

這裏用到了文件分佈式存儲,要預覽的放在了另外的文件服務器上面,因此這裏使用webclient下載,獲取到文件信息,保存在數據庫中,若是存在則直接返回。固然,你能夠使用FileStream來讀取文件的響應信息。async

獲取文件預覽的地址分佈式

根據web office apps服務的地址,文件擴展名獲取預覽的linkpost

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>
        /// <returns></returns>
        public string GetDocumentLink(string fileMD5, string ext)
        {
            string apiUrl = string.Format(ConfigManager.OWA_MY_VIEW_URL, fileMD5);
            return string.Format("{0}{1}{2}&access_token={3}", ConfigManager.OWA_URL, FindUrlByExtenstion(ext), apiUrl, fileMD5);
        }
        /// <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('.');
            }
            Dictionary<string, string> dic = new Dictionary<string, string>() 
            { 
            {"ods","/x/_layouts/xlviewerinternal.aspx?WOPISrc="},
            {"xls", "/x/_layouts/xlviewerinternal.aspx?WOPISrc="},
            {"xlsb", "/x/_layouts/xlviewerinternal.aspx?WOPISrc="},
            {"xlsm", "/x/_layouts/xlviewerinternal.aspx?WOPISrc="},
            {"xlsx", "/x/_layouts/xlviewerinternal.aspx?WOPISrc="},
            {"one", "/o/onenoteframe.aspx?WOPISrc="},
            {"onetoc2", "/o/onenoteframe.aspx?WOPISrc="},
            {"odp", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"pot", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"potm", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"potx", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"pps", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"ppsm", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"ppsx", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"ppt", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"pptm", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"pptx", "/p/PowerPointFrame.aspx?WOPISrc="},
            {"doc", "/wv/wordviewerframe.aspx?WOPISrc="},
            {"docm", "/wv/wordviewerframe.aspx?WOPISrc="},
            {"docx", "/wv/wordviewerframe.aspx?WOPISrc="},
            {"dot", "/wv/wordviewerframe.aspx?WOPISrc="},
            {"dotm", "/wv/wordviewerframe.aspx?WOPISrc="},
            {"dotx", "/wv/wordviewerframe.aspx?WOPISrc="},
            {"pdf", "/wv/wordviewerframe.aspx?WOPISrc="}
            };
            return dic[ext];
        }
    }
}

web office apps 預覽接口回調使用的api時,須要注意儘可能傳遞id之類,若是傳遞name,文件名涉及到了中文,會有編碼的問題,因此我這裏傳遞的是文件的md5值。

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
{
    /// <summary>
    /// Primary class for WOPI interface.  Supporting the 2 minimal API calls
    /// requred for base level View
    /// </summary>
    public class FilesController : ApiController
    {
        IFileHelper _fileHelper;
        HttpResponseMessage _response;
        /// <summary>
        /// Base constructor
        /// </summary>
        public FilesController()
        {
            _fileHelper = new FileHelper();
            _response = new HttpResponseMessage(HttpStatusCode.Accepted);
            //容許哪些url能夠跨域請求到本域
            _response.Headers.Add("Access-Control-Allow-Origin", "*");
            //容許的請求方法,通常是GET,POST,PUT,DELETE,OPTIONS
            _response.Headers.Add("Access-Control-Allow-Methods", "POST");
            //容許哪些請求頭能夠跨域
            _response.Headers.Add("Access-Control-Allow-Headers", "x-requested-with,content-type");
        }
        /// <summary>
        /// Required for WOPI interface - on initial view
        /// </summary>
        /// <param name="name">file name</param>
        /// <returns></returns>        
        public async Task<CheckFileInfo> Get(string name)
        {
            return await _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>
        public async Task<CheckFileInfo> Get(string name, string access_token)
        {
            return await _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>
        public async Task<HttpResponseMessage> GetFile(string name, string access_token)
        {
            try
            {
                _response.StatusCode = HttpStatusCode.OK;
                FileBusiness FileBusiness = new FileBusiness();
                var file = FileBusiness.FindFileByMD5(name);
                if (file != null)
                {
                    WebClient webClient = new WebClient();
                    byte[] buffer = await webClient.DownloadDataTaskAsync(file.Url);
                    MemoryStream stream = new MemoryStream(buffer);
                    _response.Content = new StreamContent(stream);
                    _response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                }
                return _response;
            }
            catch (Exception ex)
            {
                _response.StatusCode = HttpStatusCode.InternalServerError;
                var stream = new MemoryStream(UTF8Encoding.Default.GetBytes(ex.Message ?? ""));
                _response.Content = new StreamContent(stream);
                return _response;
            }
        }
    }
}

路由配置

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace WebSite.OfficeViewerService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服務
            // Web API 路由
            config.Routes.MapHttpRoute(
                 name: "Contents",
                 routeTemplate: "api/wopi/files/{name}/contents",
                 defaults: new { controller = "files", action = "GetFile" }
                 );
            config.Routes.MapHttpRoute(
                name: "FileInfo",
                routeTemplate: "api/wopi/files/{name}",
                defaults: new { controller = "Files", action = "Get" }
                );
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { controller = "Files", id = RouteParameter.Optional }
            );
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.Mvc;
using WebSite.OfficeViewerService.Helpers;

namespace WebSite.OfficeViewerService.Controllers
{
    public class HomeController : Controller
    {
        IFileHelper _fileHelper = new FileHelper();
        public ActionResult Index()
        {
            return View();
        }
        public async Task<ActionResult> Viewer(string url, string name)
        {
            string itcode = string.Empty;
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("Sorry,Url is errr,the file is not found");
                }
string fileExt = url.Substring(url.LastIndexOf('.')); WopiAppHelper wopiHelper = new WopiAppHelper(); FileBusiness FileBusiness = new FileBusiness(); var file = FileBusiness.FindFileByUrl(url); string fileMD5 = string.Empty; if (file == null) { WebClient webClient = new WebClient(); byte[] buffer = await webClient.DownloadDataTaskAsync(url); fileMD5 = MD5Helper.GetMD5FromFile(buffer);string sha256 = _fileHelper.GetSHA256Async(buffer); await fastDFSFileBusiness.SaveAsync(new FastDFSFile { Dt = DateTime.Now, FileMd5 = fileMD5, FileName = name, FileSize = buffer.Length, Itcode = itcode, Url = url, SHA256 = sha256 }); } else { fileMD5 = file.FileMd5; } var result = wopiHelper.GetDocumentLink(fileMD5, fileExt); return Redirect(result); } catch (Exception ex) { ViewBag.Message = ex.Message; } return View(); } } }

包裝預覽接口,其它應用經過傳遞文件的url和文件名稱,而後跳轉到實際的預覽界面。簡單粗暴,不用每一個應用都在實現上面的方法。

相關文章
相關標籤/搜索