#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)
}