在没有Microsoft.Office.Interop的情况下,将.NET doc和docx格式转换为.NET Core中的PDF

时间:2017-10-05 08:03:47

标签: c# pdf ms-word .net-core

我需要在浏览器中显示Word .doc.docx文件。没有真正的客户端方式,出于法律原因,这些文档无法与Google文档或Microsoft Office 365共享。

浏览器无法显示Word,但可以显示PDF,因此我想在服务器上将这些文档转换为PDF,然后显示它。

我知道可以使用Microsoft.Office.Interop.Word完成此操作,但我的应用程序是.NET Core,无法访问Office互操作。它可以在Azure上运行,但它也可以在Docker容器中运行。

似乎有很多类似的问题,但大多数人都在询问全框架.NET,或者假设服务器是Windows操作系统,任何答案对我都没有用。

如果{/ 1}} 无法访问.doc,如何将.docx.pdf文件转换为Microsoft.Office.Interop.Word

8 个答案:

答案 0 :(得分:44)

这就是PITA,难怪所有第三方解决方案都要为每位开发者收取500美元。

好消息是Open XML SDK recently added support for .Net Standard所以看起来你对.docx格式感到满意。

目前坏消息 .NET Core上的PDF生成库没有太多选择。因为看起来你不想支付一个而且你不能合法地使用第三方服务,所以我们别无选择,只能自己动手。

主要问题是将Word文档内容转换为PDF。其中一种流行的方法是将Docx读入HTML并将其导出为PDF。很难找到,但有支持将Docx转换为HTML的OpenXMLSDK- PowerTools 的.Net Core版本。拉动请求“即将被接受”,你可以从这里得到它:

https://github.com/OfficeDev/Open-Xml-PowerTools/tree/abfbaac510d0d60e2f492503c60ef897247716cf

现在我们可以将文档内容提取到HTML,我们需要将其转换为PDF。有一些库可以将HTML转换为PDF,例如DinkToPdf是围绕Webkit HTML到PDF库libwkhtmltox的跨平台包装。

我认为DinkToPdf优于https://code.msdn.microsoft.com/How-to-export-HTML-to-PDF-c5afd0ce

Docx到HTML

让我们完全放下这个,下载OpenXMLSDK-PowerTools .Net Core项目并构建它(只是OpenXMLPowerTools.Core和OpenXMLPowerTools.Core.Example - 忽略其他项目)。将OpenXMLPowerTools.Core.Example设置为StartUp项目。运行控制台项目:

static void Main(string[] args)
{
    var source = Package.Open(@"test.docx");
    var document = WordprocessingDocument.Open(source);
    HtmlConverterSettings settings = new HtmlConverterSettings();
    XElement html = HtmlConverter.ConvertToHtml(document, settings);

    Console.WriteLine(html.ToString());
    var writer = File.CreateText("test.html");
    writer.WriteLine(html.ToString());
    writer.Dispose();
    Console.ReadLine();

如果您运行该项目,您将看到HTML看起来几乎与Word文档中的内容完全相同:

enter image description here

但是,如果您尝试使用带有图片或链接的Word文档,您会发现它们已丢失或损坏。

此CodeProject文章解决了这些问题:https://www.codeproject.com/Articles/1162184/Csharp-Docx-to-HTML-to-Docx

我必须更改static Uri FixUri(string brokenUri)方法才能返回Uri,并添加了用户友好的错误消息。

static void Main(string[] args)
{
    var fileInfo = new FileInfo(@"c:\temp\MyDocWithImages.docx");
    string fullFilePath = fileInfo.FullName;
    string htmlText = string.Empty;
    try
    {
        htmlText = ParseDOCX(fileInfo);
    }
    catch (OpenXmlPackageException e)
    {
        if (e.ToString().Contains("Invalid Hyperlink"))
        {
            using (FileStream fs = new FileStream(fullFilePath,FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                UriFixer.FixInvalidUri(fs, brokenUri => FixUri(brokenUri));
            }
            htmlText = ParseDOCX(fileInfo);
        }
    }

    var writer = File.CreateText("test1.html");
    writer.WriteLine(htmlText.ToString());
    writer.Dispose();
}

public static Uri FixUri(string brokenUri)
{
    string newURI = string.Empty;
    if (brokenUri.Contains("mailto:"))
    {
        int mailToCount = "mailto:".Length;
        brokenUri = brokenUri.Remove(0, mailToCount);
        newURI = brokenUri;
    }
    else
    {
        newURI = " ";
    }
    return new Uri(newURI);
}

public static string ParseDOCX(FileInfo fileInfo)
{
    try
    {
        byte[] byteArray = File.ReadAllBytes(fileInfo.FullName);
        using (MemoryStream memoryStream = new MemoryStream())
        {
            memoryStream.Write(byteArray, 0, byteArray.Length);
            using (WordprocessingDocument wDoc =
                                        WordprocessingDocument.Open(memoryStream, true))
            {
                int imageCounter = 0;
                var pageTitle = fileInfo.FullName;
                var part = wDoc.CoreFilePropertiesPart;
                if (part != null)
                    pageTitle = (string)part.GetXDocument()
                                            .Descendants(DC.title)
                                            .FirstOrDefault() ?? fileInfo.FullName;

                WmlToHtmlConverterSettings settings = new WmlToHtmlConverterSettings()
                {
                    AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }",
                    PageTitle = pageTitle,
                    FabricateCssClasses = true,
                    CssClassPrefix = "pt-",
                    RestrictToSupportedLanguages = false,
                    RestrictToSupportedNumberingFormats = false,
                    ImageHandler = imageInfo =>
                    {
                        ++imageCounter;
                        string extension = imageInfo.ContentType.Split('/')[1].ToLower();
                        ImageFormat imageFormat = null;
                        if (extension == "png") imageFormat = ImageFormat.Png;
                        else if (extension == "gif") imageFormat = ImageFormat.Gif;
                        else if (extension == "bmp") imageFormat = ImageFormat.Bmp;
                        else if (extension == "jpeg") imageFormat = ImageFormat.Jpeg;
                        else if (extension == "tiff")
                        {
                            extension = "gif";
                            imageFormat = ImageFormat.Gif;
                        }
                        else if (extension == "x-wmf")
                        {
                            extension = "wmf";
                            imageFormat = ImageFormat.Wmf;
                        }

                        if (imageFormat == null) return null;

                        string base64 = null;
                        try
                        {
                            using (MemoryStream ms = new MemoryStream())
                            {
                                imageInfo.Bitmap.Save(ms, imageFormat);
                                var ba = ms.ToArray();
                                base64 = System.Convert.ToBase64String(ba);
                            }
                        }
                        catch (System.Runtime.InteropServices.ExternalException)
                        { return null; }

                        ImageFormat format = imageInfo.Bitmap.RawFormat;
                        ImageCodecInfo codec = ImageCodecInfo.GetImageDecoders()
                                                    .First(c => c.FormatID == format.Guid);
                        string mimeType = codec.MimeType;

                        string imageSource =
                                string.Format("data:{0};base64,{1}", mimeType, base64);

                        XElement img = new XElement(Xhtml.img,
                                new XAttribute(NoNamespace.src, imageSource),
                                imageInfo.ImgStyleAttribute,
                                imageInfo.AltText != null ?
                                    new XAttribute(NoNamespace.alt, imageInfo.AltText) : null);
                        return img;
                    }
                };

                XElement htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings);
                var html = new XDocument(new XDocumentType("html", null, null, null),
                                                                            htmlElement);
                var htmlString = html.ToString(SaveOptions.DisableFormatting);
                return htmlString;
            }
        }
    }
    catch
    {
        return "The file is either open, please close it or contains corrupt data";
    }
}

现在我们可以获得图片:

enter image description here

如果您只想在Web浏览器中显示Word .docx文件,最好不要将HTML转换为PDF,因为这会显着增加带宽。您可以使用VPP技术将HTML存储在文件系统,云或dB中。

<小时/>

HTML to PDF

接下来我们需要做的是将HTML传递给DinkToPdf。下载DinkToPdf(90 MB)解决方案。构建解决方案 - 需要一段时间才能恢复所有软件包以及编译解决方案。

重要:

  

如果要在Linux和Windows上运行,DinkToPdf库需要项目根目录中的libwkhtmltox.so和libwkhtmltox.dll文件。如果需要,还有一个适用于Mac的libwkhtmltox.dylib文件。

这些dll位于v0.12.4文件夹中。根据您的PC,32或64位,将3个文件复制到DinkToPdf-master \ DinkToPfd.TestConsoleApp \ bin \ Debug \ netcoreapp1.1文件夹。

重要2:

  

确保在Docker映像或Linux计算机上安装了libgdiplus。 libwkhtmltox.so库取决于它。

将DinkToPfd.TestConsoleApp设置为StartUp项目并更改Program.cs文件以从使用Open-Xml-PowerTools而不是Lorium Ipsom文本保存的HTML文件中读取htmlContent。

var doc = new HtmlToPdfDocument()
{
    GlobalSettings = {
        ColorMode = ColorMode.Color,
        Orientation = Orientation.Landscape,
        PaperSize = PaperKind.A4,
    },
    Objects = {
        new ObjectSettings() {
            PagesCount = true,
            HtmlContent = File.ReadAllText(@"C:\TFS\Sandbox\Open-Xml-PowerTools-abfbaac510d0d60e2f492503c60ef897247716cf\ToolsTest\test1.html"),
            WebSettings = { DefaultEncoding = "utf-8" },
            HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
            FooterSettings = { FontSize = 9, Right = "Page [page] of [toPage]" }
        }
    }
};

Docx与PDF的结果令人印象深刻,我怀疑很多人会发现很多差异(特别是如果他们从未看过原版):

enter image description here

聚苯乙烯。我意识到您想要将.doc.docx都转换为PDF。我建议您自己使用特定的非服务器Windows / Microsoft技术将.doc转换为docx。 doc格式为二进制格式,不适用于server side automation of office

答案 1 :(得分:9)

使用LibreOffice二进制文件

LibreOffice项目是MS Office的开源跨平台替代方案。我们可以使用其功能将docdocx文件导出到PDF。目前,LibreOffice没有适用于.NET的官方API,因此,我们将直接与soffice二进制文件进行对话。

这是一种&#34; hacky&#34;解决方案,但我认为这是解决方案,可以减少错误并保持成本。此方法的另一个优点是您不限于从docdocx进行转换:您可以从每种格式的LibreOffice支持转换它(例如odt,html,电子表格等)。

实施

我写了一个使用c#二进制文件的简单soffice程序。这只是一个概念验证(我在c#中的第一个程序)。只有安装了LibreOffice软件包后,它才会支持Windows开箱即用Linux

这是main.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Reflection;

namespace DocToPdf
{
    public class LibreOfficeFailedException : Exception
    {
        public LibreOfficeFailedException(int exitCode)
            : base(string.Format("LibreOffice has failed with {}", exitCode))
            {}
    }

    class Program
    {
        static string getLibreOfficePath() {
            switch (Environment.OSVersion.Platform) {
                case PlatformID.Unix:
                    return "/usr/bin/soffice";
                case PlatformID.Win32NT:
                    string binaryDirectory = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                    return binaryDirectory + "\\Windows\\program\\soffice.exe";
                default:
                    throw new PlatformNotSupportedException ("Your OS is not supported");
            }
        }

        static void Main(string[] args) {
            string libreOfficePath = getLibreOfficePath();

            // FIXME: file name escaping: I have not idea how to do it in .NET.
            ProcessStartInfo procStartInfo = new ProcessStartInfo(libreOfficePath, string.Format("--convert-to pdf --nologo {0}", args[0]));
            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = true;
            procStartInfo.WorkingDirectory = Environment.CurrentDirectory;

            Process process = new Process() { StartInfo =      procStartInfo, };
            process.Start();
            process.WaitForExit();

            // Check for failed exit code.
            if (process.ExitCode != 0) {
                throw new LibreOfficeFailedException(process.ExitCode);
            }
        }
    }
}

资源

结果

我在Arch Linux上测试过它,用mono编译。我使用mon和Linux二进制文件运行它,并使用wine:使用Windows二进制文件。

您可以在Tests目录中找到结果:

输入文件:testdoc.doctestdocx.docx

输出:

答案 2 :(得分:2)

我最近使用FreeSpire.Doc完成了此操作。免费版本限制为3页,但是可以使用类似的方法轻松地将docx文件转换为PDF

    private void ConvertToPdf()
    {
        try
        {
            for (int i = 0; i < listOfDocx.Count; i++)
            {
                CurrentModalText = "Converting To PDF";
                CurrentLoadingNum += 1;

                string savePath = PdfTempStorage + i + ".pdf";
                listOfPDF.Add(savePath);

                Spire.Doc.Document document = new Spire.Doc.Document(listOfDocx[i], FileFormat.Auto);
                document.SaveToFile(savePath, FileFormat.PDF);
            }
        }
        catch (Exception e)
        {
            throw e;
        }
    }

然后我使用itextsharp.pdf将这些单独的pdf缝在一起。

 public static byte[] concatAndAddContent(List<byte[]> pdfByteContent, List<MailComm> localList)
    {

        using (var ms = new MemoryStream())
        {
            using (var doc = new Document())
            {
                using (var copy = new PdfSmartCopy(doc, ms))
                {
                    doc.Open();
                    //add checklist at the start
                    using (var db = new StudyContext())
                    {
                        var contentId = localList[0].ContentID;
                        var temp = db.MailContentTypes.Where(x => x.ContentId == contentId).ToList();
                        if (!temp[0].Code.Equals("LAB"))
                        {
                            pdfByteContent.Insert(0, CheckListCreation.createCheckBox(localList));
                        }
                    }

                    //Loop through each byte array
                    foreach (var p in pdfByteContent)
                    {

                        //Create a PdfReader bound to that byte array
                        using (var reader = new PdfReader(p))
                        {

                            //Add the entire document instead of page-by-page
                            copy.AddDocument(reader);
                        }
                    }

                    doc.Close();
                }
            }

            //Return just before disposing
            return ms.ToArray();
        }
    }

我不知道这是否适合您的用例,因为您没有指定要编写的文档的大小,但是如果它们的页数超过3页,或者您可以将它们控制为少于3页,它将允许您将它们转换为pdfs

答案 3 :(得分:2)

这增加了杰里米·汤普森(Jeremy Thompson)非常有用的答案。除了word文档主体,我还希望将word文档的页眉(和页脚)转换为HTML。我不想修改Open-Xml-PowerTools,所以我根据Jeremy的示例修改了Main()和ParseDOCX(),并添加了两个新功能。现在,ParseDOCX可以接受字节数组,因此原始Word Docx不会被修改。

static void Main(string[] args)
{
    var fileInfo = new FileInfo(@"c:\temp\MyDocWithImages.docx");
    byte[] fileBytes = File.ReadAllBytes(fileInfo.FullName);
    string htmlText = string.Empty;
    string htmlHeader = string.Empty;
    try
    {
        htmlText = ParseDOCX(fileBytes, fileInfo.Name, false);
        htmlHeader = ParseDOCX(fileBytes, fileInfo.Name, true);
    }
    catch (OpenXmlPackageException e)
    {
        if (e.ToString().Contains("Invalid Hyperlink"))
        {
            using (FileStream fs = new FileStream(fullFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                UriFixer.FixInvalidUri(fs, brokenUri => FixUri(brokenUri));
            }
            htmlText = ParseDOCX(fileBytes, fileInfo.Name, false);
            htmlHeader = ParseDOCX(fileBytes, fileInfo.Name, true);
        }
    }

    var writer = File.CreateText("test1.html");
    writer.WriteLine(htmlText.ToString());
    writer.Dispose();
    var writer2 = File.CreateText("header1.html");
    writer2.WriteLine(htmlHeader.ToString());
    writer2.Dispose();
}

private static string ParseDOCX(byte[] fileBytes, string filename, bool headerOnly)
{
    try
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            memoryStream.Write(fileBytes, 0, fileBytes.Length);
            using (WordprocessingDocument wDoc = WordprocessingDocument.Open(memoryStream, true))
            {
                int imageCounter = 0;
                var pageTitle = filename;
                var part = wDoc.CoreFilePropertiesPart;
                if (part != null)
                {
                    pageTitle = (string)part.GetXDocument()
                                            .Descendants(DC.title)
                                            .FirstOrDefault() ?? filename;
                }

                WmlToHtmlConverterSettings settings = new WmlToHtmlConverterSettings()
                {
                    AdditionalCss = "body { margin: 1cm auto; max-width: 20cm; padding: 0; }",
                    PageTitle = pageTitle,
                    FabricateCssClasses = true,
                    CssClassPrefix = "pt-",
                    RestrictToSupportedLanguages = false,
                    RestrictToSupportedNumberingFormats = false,
                    ImageHandler = imageInfo =>
                    {
                        ++imageCounter;
                        string extension = imageInfo.ContentType.Split('/')[1].ToLower();
                        ImageFormat imageFormat = null;
                        if (extension == "png") imageFormat = ImageFormat.Png;
                        else if (extension == "gif") imageFormat = ImageFormat.Gif;
                        else if (extension == "bmp") imageFormat = ImageFormat.Bmp;
                        else if (extension == "jpeg") imageFormat = ImageFormat.Jpeg;
                        else if (extension == "tiff")
                        {
                            extension = "gif";
                            imageFormat = ImageFormat.Gif;
                        }
                        else if (extension == "x-wmf")
                        {
                            extension = "wmf";
                            imageFormat = ImageFormat.Wmf;
                        }

                        if (imageFormat == null) return null;

                        string base64 = null;
                        try
                        {
                            using (MemoryStream ms = new MemoryStream())
                            {
                                imageInfo.Bitmap.Save(ms, imageFormat);
                                var ba = ms.ToArray();
                                base64 = System.Convert.ToBase64String(ba);
                            }
                        }
                        catch (System.Runtime.InteropServices.ExternalException)
                        { return null; }

                        ImageFormat format = imageInfo.Bitmap.RawFormat;
                        ImageCodecInfo codec = ImageCodecInfo.GetImageDecoders()
                                                    .First(c => c.FormatID == format.Guid);
                        string mimeType = codec.MimeType;

                        string imageSource =
                                string.Format("data:{0};base64,{1}", mimeType, base64);

                        XElement img = new XElement(Xhtml.img,
                                new XAttribute(NoNamespace.src, imageSource),
                                imageInfo.ImgStyleAttribute,
                                imageInfo.AltText != null ?
                                    new XAttribute(NoNamespace.alt, imageInfo.AltText) : null);
                        return img;
                    }
                };

                // Put header into document body, and remove everything else
                if (headerOnly)
                {
                    MoveHeaderToDocumentBody(wDoc);
                }

                XElement htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings);
                var html = new XDocument(new XDocumentType("html", null, null, null),
                                                                            htmlElement);
                var htmlString = html.ToString(SaveOptions.DisableFormatting);
                return htmlString;
            }
        }
    }
    catch
    {
        return "The file is either open, please close it or contains corrupt data";
    }
}

private static void MoveHeaderToDocumentBody(WordprocessingDocument wDoc)
{
    MainDocumentPart mainDocument = wDoc.MainDocumentPart;
    XElement docRoot = mainDocument.GetXDocument().Root;
    XElement body = docRoot.Descendants(W.body).First();
    // Only handles first header. Header info: https://docs.microsoft.com/en-us/office/open-xml/how-to-replace-the-header-in-a-word-processing-document
    HeaderPart header = mainDocument.HeaderParts.FirstOrDefault();
    XElement headerRoot = header.GetXDocument().Root;

    AddXElementToBody(headerRoot, body);

    // document body will have new headers when we return from this function
    return;
}

private static void AddXElementToBody(XElement sourceElement, XElement body)
{
    // Clone the children nodes
    List<XElement> children = sourceElement.Elements().ToList();
    List<XElement> childClones = children.Select(el => new XElement(el)).ToList();

    // Clone the section properties nodes
    List<XElement> sections = body.Descendants(W.sectPr).ToList();
    List<XElement> sectionsClones = sections.Select(el => new XElement(el)).ToList();

    // clear body
    body.Descendants().Remove();

    // add source elements to body
    foreach (var child in childClones)
    {
        body.Add(child);
    }

    // add section properties to body
    foreach (var section in sectionsClones)
    {
        body.Add(section);
    }

    // get text from alternate content if needed - either choice or fallback node
    XElement alternate = body.Descendants(MC.AlternateContent).FirstOrDefault();
    if (alternate != null)
    {
        var choice = alternate.Descendants(MC.Choice).FirstOrDefault();
        var fallback = alternate.Descendants(MC.Fallback).FirstOrDefault();
        if (choice != null)
        {
            var choiceChildren = choice.Elements();
            foreach(var choiceChild in choiceChildren)
            {
                body.Add(choiceChild);
            }
        }
        else if (fallback != null)
        {
            var fallbackChildren = fallback.Elements();
            foreach (var fallbackChild in fallbackChildren)
            {
                body.Add(fallbackChild);
            }
        }
    }
}

您可以添加类似的方法来处理Word文档页脚。

以我为例,然后将HTML文件转换为图像(使用Net-Core-Html-To-Image,也基于wkHtmlToX)。我将标题和正文图像组合在一起(使用Magick.NET-Q16-AnyCpu),将标题图像放在正文图像的顶部。

答案 4 :(得分:1)

对不起,我没有足够的声誉来发表评论,但我想在杰里米·汤普森的答案上加上我的两分钱。希望这对某人有所帮助。

当我查看Jeremy Thompson的答案时,下载OpenXMLSDK-PowerTools并运行OpenXMLPowerTools.Core.Example后,出现类似

的错误
the specified package is invalid. the main part is missing

在线

var document = WordprocessingDocument.Open(source);

在奋斗了几个小时之后,我发现复制到bin文件中的test.docx只有1kb。要解决此问题,请右键单击test.docx> Properties,将Copy to Output Directory设置为Copy always可解决此问题。

希望对我这样的新手有所帮助:)

答案 5 :(得分:0)

为了即使使用占位符也可以将DOCX转换为PDF,我在 MIT下使用.NET CORE创建了一个免费的“ Report-From-DocX-HTML-To-PDF-Converter” 库。许可证,因为我非常不满意,以至于没有简单的解决方案,而且所有商业解决方案都非常昂贵。您可以在此处找到它的详细说明和示例项目:

https://github.com/smartinmedia/Net-Core-DocX-HTML-To-PDF-Converter

您只需要免费的LibreOffice。我建议使用LibreOffice Portable版,因此它不会更改服务器设置中的任何内容。看一下文件“ soffice.exe”(在Linux上的名称不同)所在的位置,因为您需要用它来填充变量“ locationOfLibreOfficeSoffice”。

从DOCX转换为HTML的方法如下:

string locationOfLibreOfficeSoffice =   @"C:\PortableApps\LibreOfficePortable\App\libreoffice\program\soffice.exe";

var docxLocation = "MyWordDocument.docx";

var rep = new ReportGenerator(locationOfLibreOfficeSoffice);

//Convert from DOCX to PDF
test.Convert(docxLocation, Path.Combine(Path.GetDirectoryName(docxLocation), "Test-Template-out.pdf"));


//Convert from DOCX to HTML
test.Convert(docxLocation, Path.Combine(Path.GetDirectoryName(docxLocation), "Test-Template-out.html"));

如您所见,您还可以从DOCX转换为HTML。另外,您可以将占位符放入Word文档中,然后可以用值“填充”。但是,这不在您的问题范围内,但是您可以在Github(README)上阅读有关该内容的信息。

答案 6 :(得分:0)

如果您可以访问 Office 365,则可以实施替代解决方案。这比我之前的答案具有更少的限制,但需要购买。

我获得了一个图形 API 令牌、我想要使用的站点以及我想要使用的驱动器。

之后我获取了 docx 的字节数组

    public static async Task<Stream> GetByteArrayOfDocumentAsync(string baseFilePathLocation)
    {
        var byteArray = File.ReadAllBytes(baseFilePathLocation);
        using var stream = new MemoryStream();
        stream.Write(byteArray, 0, (int) byteArray.Length);

        return stream;
    }

然后使用带有我们的图形 API 令牌的客户端设置将此流上传到图形 API

        public static async Task<string> UploadFileAsync(HttpClient client,
                                                     string siteId,
                                                     MemoryStream stream,
                                                     string driveId,
                                                     string fileName,
                                                     string folderName = "root")
    {

        var result = await client.PutAsync(
            $"https://graph.microsoft.com/v1.0/sites/{siteId}/drives/{driveId}/items/{folderName}:/{fileName}:/content",
            new ByteArrayContent(stream.ToArray()));
        var res = JsonSerializer.Deserialize<SharepointDocument>(await result.Content.ReadAsStringAsync());
        return res.id;
    }

然后我们使用给定的 api 从图形 api 下载以获取 PDF

        public static async Task<Stream> GetPdfOfDocumentAsync(HttpClient client,
                                                            string siteId,
                                                            string driveId,
                                                            string documentId)
    {


        var getRequest =
            await client.GetAsync(
                $"https://graph.microsoft.com/v1.0/sites/{siteId}/drives/{driveId}/items/{documentId}/content?format=pdf");
        return await getRequest.Content.ReadAsStreamAsync();

    }

这给出了一个由刚刚创建的文档组成的流。

答案 7 :(得分:-3)

  

我知道可以使用Microsoft.Office.Interop.Word完成此操作,但是我   该应用程序是.NET Core,并且无法访问Office互操作。

也许这是不正确的?您可以在dotnet核心中加载程序集,但是,由于dotnet核心与主机无关,因此加载互操作组件可能是一个挑战。

这是东西,尽管您不需要安装Office即可获取Office主互操作程序集。您可以尝试在不使用COM +的情况下加载程序集,尽管这可能有些棘手?我实际上不确定是否可以做到,但是从理论上讲,您应该可以做到。有没有人考虑过在不安装Office的情况下尝试此操作?

这是指向办公室PIA的链接 https://www.microsoft.com/en-us/download/confirmation.aspx?id=3508