Как передать PDF-файл с помощью API водопроводчика?

#r #api #pdf #serialization #plumber

Вопрос:

У меня есть функция API, которая принимает входные данные, получает необходимые данные с помощью этих входных данных, вызывает файл .rmd и с помощью этого файла .rmd создает файл pdf в указанном каталоге. Мне нужна оставшаяся часть моего API, чтобы взять недавно созданный pdf-файл и опубликовать его через HTTP. Однако всякий раз, когда я пытаюсь это сделать, я в конечном итоге получаю поврежденный файл в качестве вывода.

Это мой текущий код:

 #* @serializer contentType list(type="application/pdf")
#* parameter_selection
#* @param a1
#* @get /pdf

function( a1) {
  
  #Please assume that the filename location is correct. 

  filename = paste0( a1, '_','report','.pdf', sepp='')

  locale_filename = paste0('notebooks/',filename, sepp= '')

  readBin(locale_filename, "raw", n=file.info(locale_filename)$size)


}
 

Спасибо.

Комментарии:

1. К вашему сведению, sepp='' игнорируется , так как он не соответствует никаким аргументам, но ничего не добавляет; если вы имеете в виду sep='' , что это не требуется при использовании paste0 . На самом деле, если вы попытаетесь paste0('a','b',sep=' ') , вы увидите, что он не распознает его как аргумент, поэтому добавляет буквальную строку с одним символом, как в ab (там есть пробел).

2. Ваш код точно имитирует rplumber.io/articles/rendering-output.html , и когда я использую это (в FF из R-4.0.5), это работает. Вы уверены, что файл можно просматривать за пределами (до, не проходя) вашей среды водопроводчика?

3. r2evans прав в первую очередь. Тогда есть ли это в вашем коде ? ` res$setHeader(«Расположение содержимого», paste0(«вложение; имя файла=», базовое имя(locale_filename)))` для ссылки и предоставления pdf-файла в вашем браузере? Для меня этот код работает. Еще одна вещь, которую следует учитывать при работе с водопроводчиком, — это использовать полный путь, а не относительный путь для доступа к файлам, он всегда будет работать, тогда как с относительным путем это зависит.

4. Да. Файл отображается без проблем в указанной папке, но когда я пытаюсь протолкнуть этот файл через интерфейс AP, я получаю следующую ошибку: Тело ответа Не распознан тип ответа; отображение содержимого в виде текста. Я получаю что-то похожее на pdf-файл в ответе тела, но когда я пытаюсь открыть его с помощью средства просмотра PDF, я получаю сообщение об ошибке поврежденного файла. Заголовки ответов, которые я получаю, следующие: длина содержимого: 1050292 тип содержимого: приложение/pdf дата: Вторник 29 июня 2021 19:46:37 GMT

5. Где в коде я бы разместил строку: res$setHeader(«Расположение содержимого», paste0(«вложение; имя файла=», базовое имя(имя_файла)))?

Ответ №1:

Это что-то вроде этого:

 #* @serializer contentType list(type="application/pdf")
#* parameter_selection
#* @param a1
#* @get /pdf

function( a1, res) {

  #Please assume that the filename location is correct. 

  filename = paste0( a1, '_','report','.pdf', sepp='')

  locale_filename = paste0('notebooks/',filename, sepp= '')

  tmp <- tempfile()

  res$setHeader("Content-Disposition", paste0("attachment; filename=", basename(locale_filename)))

  tmp <- rmarkdown::render(file_location ,output_file = paste0(this_title, sepp=''), envir = new.env(parent = globalenv()))


  readBin(locale_filename, "raw", n=file.info(locale_filename)$size)
 

}