Search code examples
rplumber

Trouble Opening Downloaded DOCX File from Plumber API


I'm currently developing a Plumber API in R that generates and serves DOCX files. While the API appears to be working correctly, I'm facing an issue when attempting to open the downloaded DOCX file. I would appreciate any insights or suggestions to help resolve this matter.

  1. I have a Plumber endpoint that generates a Word document (DOCX) and serves it as a binary response.
  2. The generated DOCX file can be downloaded successfully, but there's an issue when attempting to open it.

If i could download the file as .zip instead if docx. that could would be nice to.

My 3 scripts :

script 1 : plumber.R

#* @param test le deuxieme doc
#* @post /generate_report_word
function(test, res) {
  
  tmp1 <- tempfile(tmpdir = getwd())
  
  output_path <- paste0(getwd(), "/report_test.docx")
  
  rmarkdown::render("report_test.Rmd", output_file = output_path, 
                    params = list(team1 = test))
  

  file_content <- readBin(output_path, "raw", n = file.info(output_path)$size)
  res$setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
  res$setHeader("Content-Disposition", sprintf("attachment; filename=%s", "rapport_word.docx"))
  res$status(200)
  res$body(file_content)
  
}

script 2 : used to run plumber.R

library(plumber)
library(rmarkdown)

r <- plumb("plumber.R")  
r$run(port=8000)

as for the report_test.RMD :

---
title: "report_test"
author: "Hello"
date: "`r Sys.Date()`"
output: word_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

## R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.

When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

```{r cars}
summary(cars)
```

## Including Plots

You can also embed plots, for example:

```{r pressure, echo=FALSE}
plot(pressure)
```

Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.

Solution

  • By default plumber will serialize everything to JSON. You would want to create a new serialize for word documents. Before you call plumb(), add these lines

    serializer_word <- function (..., type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document") 
    {
      serializer_content_type(type, function(val) {
        val
      })
    }
    register_serializer("word", serializer_word)
    

    And then change your endpoint to use that serizalize

    #* @param test le deuxieme doc
    #* @serializer word
    #* @post /generate_report_word
    function(test, res) {
      
      tmp1 <- tempfile(tmpdir = getwd())
      
      output_path <- paste0(getwd(), "/report_test.docx")
      
      rmarkdown::render("report_test.Rmd", output_file = output_path, 
                        params = list(team1 = test))
      
      file_content <- readBin(output_path, raw(), n = file.info(output_path)$size) 
      as_attachment(file_content, "rapport_word.docx")
    }