Landscape Orientation Not Working When Saving Word Stream As PDF

I am trying to download a PDF with landscape orientation and I cannot get it working.
First I create a word document by importing HTML, and then save the Word document as PDF and return as a download.

Here is a minimized version of the code:

// Create source document.
Aspose.Words.Document doc = new Aspose.Words.Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// Insert HTML
builder.MoveToDocumentStart();
builder.InsertHtml(document.Html, false);
MemoryStream stream = new MemoryStream();
doc.Save(stream, Aspose.Words.SaveFormat.Pdf);
//open the stream as a PDF
Aspose.Pdf.Document pdf = new Aspose.Pdf.Document(stream);
// Create return stream
MemoryStream returnStream = new MemoryStream();
// Save in PDF format
pdf.Save(returnStream, Aspose.Pdf.SaveFormat.Pdf);
// Return Pdf
return Convert.ToBase64String(returnStream.ToArray());

Note, if I return the Word Document stream, the Word Document will correctly have landscape orientation. It’s just the conversion\saving as pdf that fails to maintain the orientation.

Here is what I have tried:

Setting landscape in page setup:

Aspose.Words.PageSetup ps = builder.PageSetup;
// NOTE: Changing Orientation swaps PageWidth and PageHeight
ps.Orientation = Aspose.Words.Orientation.Landscape;

Keep source formatting:

// import options
ImportFormatOptions importFormatOptions = new ImportFormatOptions();
importFormatOptions.IgnoreHeaderFooter = true;
importFormatOptions.KeepSourceNumbering = false;

Setting all Word sections to Landscape:

foreach (Aspose.Words.Section section in doc.Sections)
{
    section.PageSetup.Orientation = Aspose.Words.Orientation.Landscape;
    section.PageSetup.LeftMargin = document.LeftMargin != null ? ConvertUtil.InchToPoint(document.LeftMargin.Value) : ConvertUtil.InchToPoint(1.0); ;
    section.PageSetup.RightMargin = document.RightMargin != null ? ConvertUtil.InchToPoint(document.RightMargin.Value) : ConvertUtil.InchToPoint(1.0); ;
}

Setting Landscape on the PDF side:

pdf.PageInfo.IsLandscape = true;

None of these options worked.

Any ideas?

I am using Version 23.4.0

Thank You,

Coty

@martincoty77 In your minimized code example Aspose.PDF is not required. It is enough to use the following code to convert HTML to PDF and return it as base64 string:

// Create source document.
Aspose.Words.Document doc = new Aspose.Words.Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// Insert HTML
builder.MoveToDocumentStart();
builder.InsertHtml(document.Html, false);
using (MemoryStream stream = new MemoryStream())
{
    doc.Save(stream, Aspose.Words.SaveFormat.Pdf);
    return Convert.ToBase64String(stream.ToArray());
}

If it is required to change page orientation of the document to landscape you can modify the code like this:

// Create source document.
Aspose.Words.Document doc = new Aspose.Words.Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// Insert HTML
builder.MoveToDocumentStart();
builder.InsertHtml(document.Html, false);

// Chnage page orientation.
foreach (Section s in doc.Sections)
    s.PageSetup.Orientation = Orientation.Landscape;

using (MemoryStream stream = new MemoryStream())
{
    doc.Save(stream, Aspose.Words.SaveFormat.Pdf);
    return Convert.ToBase64String(stream.ToArray());
}

If the problem still persist on your side, please attach your input HTML, the problematic and expected output PDF documents. We will check the issue and provide you more information.

Thanks, I will test this out.
Also one note, the HTML, margins and orientation are passed into this method, so if there is a way to create a document with HTML in landscape orientation from the beginning (instead of changing it after created) I would be able to do it that way as well.

The PDF is still not being downloaded in Portrait Orientation. I really simplified the HTML to make sure it wasn’t something with the CSS/Html. I was going to attach the html as a text file but I don’t see how you attach a file? But it is basically,

{a few rows and columns with text}

Maybe I am doing something wrong with how I am returning the stream to the browser?
The call is executed from JavaScript in Angular.

this._http.post(exportUrl, model, { responseType: "blob", headers: this.headers }).pipe(map((res) => {
    return new Blob([res], { type: "application/pdf" });
})).subscribe((res) => {
    this.fileUrl = this.sanitizer.bypassSecurityTrustUrl(
        URL.createObjectURL(res)
    );
    this.printing = false;
    setTimeout((x) => {
        this.excelLink.nativeElement.click();
    }, 0);
}, error => {
    this.showError(error);
});

It hits an API controller:

[ProducesResponseType(typeof(FileContentResult), (int)HttpStatusCode.OK)]
public FileContentResult ExportReportPdf([FromBody] DocumentHtmlModel document)
{
    var stream = _service.GetReportPdfMemoryStream(document);
    return File(stream.ToArray(), MediaTypeNames.Application.Pdf, document.Name);
}

To a service layer, which calls an External API document service:

public MemoryStream GetReportPdfMemoryStream(DocumentHtmlModel document)
{
    MemoryStream ms = new MemoryStream();
    using (var client = new HttpClient())
    {
        Task<HttpResponseMessage> response = client.PostAsync(_pdfExportUrl,
                                                                new StringContent(JsonConvert.SerializeObject(document), Encoding.UTF8, "application/json"));

        string result = response.Result.Content.ReadAsStringAsync().Result.Replace("\"", string.Empty);
        byte[] bytes = Convert.FromBase64String(result);
        ms = new MemoryStream(bytes);

    }
    return ms;
}

And here is the document service, which I again simplified, but this is everything that is being hit and returning the PDF in portrait.

[HttpPost]
[Route("MyRouteName")]
public string SaveAsPdf(DocumentHtmlModel document)
{
    string name = document.Name;
    name = System.Text.RegularExpressions.Regex.Replace(name, @"[^0-9a-zA-Z_ ]", "", System.Text.RegularExpressions.RegexOptions.Compiled);
    name = name.Replace(" ", "-");

    // Create source document.
    Aspose.Words.Document doc = new Aspose.Words.Document();

    DocumentBuilder builder = new DocumentBuilder(doc);

    Aspose.Words.PageSetup ps = builder.PageSetup;

    // Set default page width and height
    ps.PageWidth = 792;
    ps.PageHeight = 612;

    // Set default page size to Standard 8.5x11 inch/portrait
    if (document.IsLandscape)
    {
        // NOTE: Changing Orientation swaps PageWidth and PageHeight
        ps.Orientation = Aspose.Words.Orientation.Landscape;
    }

    // Set dynamic Margins or default
    ps.TopMargin = document.TopMargin != null ? ConvertUtil.InchToPoint(document.TopMargin.Value) : ConvertUtil.InchToPoint(1.0);
    ps.BottomMargin = document.BottomMargin != null ? ConvertUtil.InchToPoint(document.BottomMargin.Value) : ConvertUtil.InchToPoint(1.0);
    ps.LeftMargin = document.LeftMargin != null ? ConvertUtil.InchToPoint(document.LeftMargin.Value) : ConvertUtil.InchToPoint(1.0);
    ps.RightMargin = document.RightMargin != null ? ConvertUtil.InchToPoint(document.RightMargin.Value) : ConvertUtil.InchToPoint(1.0);

    builder.MoveToDocumentStart();

    builder.InsertHtml(document.Html, false);

    // Chnage page orientation.
    foreach (Aspose.Words.Section s in doc.Sections)
        s.PageSetup.Orientation = Aspose.Words.Orientation.Landscape;

    using (MemoryStream stream = new MemoryStream())
    {
        doc.Save(stream, Aspose.Words.SaveFormat.Pdf);
        stream.Seek(0, SeekOrigin.Begin);
        return Convert.ToBase64String(stream.ToArray());
    }
}

Any help is appreciated, thank you.

@martincoty77 Could you please attach your input HTML and output PDF here for our reference? We will check the documents and provide you more information.

Html_PDF.zip (36.1 KB)

Here is the simplified version of the HTML and PDF that I ran through the above code.

Thanks!

@martincoty77 The problem is in the following code:

// Set default page width and height
ps.PageWidth = 792;
ps.PageHeight = 612;

Normally, it is supposed that height is greater than width of the page. Please change your code like this:

// Set default page width and height
ps.PageHeight = 792;
ps.PageWidth = 612;

This worked! Thanks Alexey.
This was supposed to be handled by this code:

if (document.IsLandscape)
{
    // NOTE: Changing Orientation swaps PageWidth and PageHeight
    ps.Orientation = Aspose.Words.Orientation.Landscape;
}

And it actually does switch the page height and width as you can see when debugging…

However, this makes it print in Portrait! So I am guessing this looks like a bug?

Setting it this way does work as well, so it seems the issue is with setting the Orientation on the PageSetup object.

Thanks for your help.

@martincoty77 Actually there is no bug. Setting PageSetup.Orientation swaps page width and height. But in your case Width is greater than Height so after swapping page looks like in portrait orientation. When document is created from scratch as in your case the only section in the created document has portrait orientation, so you should set page size accordingly, Height is greater than Width, then after changing page orientations Width and Height will be swapped and the result will be correct.

Wow, I literally had the page width and height incorrect the whole time, and switching to landscape was swapping it back to portrait height and width.

Thanks for the assist!

1 Like