Search code examples
c#asp.net.net.net-5libreoffice

Web API cannot execute soffice.exe --convert-to pdf command


I want to upload a docx file via my API and it needs to return me a pdf file converted by the libreoffice soffice.exe process.

But this return me an error :

Error: source file could not be loaded

This error is throw by the soffice.exe process.

When I try to execute the soffice.exe process directly (not by the api call), he convert my docx file to pdf successfully.

My code :

Controller:

[HttpPost]
public IActionResult Post(IFormFile docxFile)
{
    if (docxFile == null)
    {
        return BadRequest();
    }
    
    if (docxFile.ContentType != "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
    {
        ModelState.AddModelError("message", "Wrong file type provided. Only docx file are accepted.");
        return UnprocessableEntity(ModelState);
    }

    string filePath = "C:\\temp.docx";

    using (Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
    {
        docxFile.CopyTo(stream);
    }
    
    ProcessStartInfo procStartInfo =
        new("C:\\Program\\LibreOffice\\program\\soffice.exe", $"--convert-to pdf --nologo '{Path.GetFileName(Path.GetFullPath(filePath))}'")
        {
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            WindowStyle = ProcessWindowStyle.Normal,
            CreateNoWindow = true,
            WorkingDirectory = Path.GetDirectoryName(Path.GetFullPath(filePath)) ?? string.Empty
        };

    using (Process process = new() {StartInfo = procStartInfo,})
    {
        process.OutputDataReceived += (sender, data) => Console.WriteLine(data.Data);
        process.ErrorDataReceived += (sender, data) => Console.WriteLine(data.Data);
        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
        process.WaitForExit();
    }
    
    FileStream fileStream = System.IO.File.Open(filePath.Replace(".docx", ".pdf"), FileMode.Open);

    return File(fileStream, "application/octet-stream", Path.GetFileName(fileStream.Name));
    
}

Specificities :

  • ASP.NET Web Api .Net 5
  • Libre Office version : 7.1.5

Solution

  • May be this function {Path.GetFileName(Path.GetFullPath(filePath))}? From what I understand, it returns only the filename and the extension from a path as described in this example from Microsoft

    Why don't you use directly your variable filePath?

    EDIT: I just noticed you are using WorkingDirectory for the process. Soffice may not work with relative paths for its arguments.