Skip to contents

Looks the same as shiny::downloadButton(), but Chinese file names save correctly in every browser: the last part of the URL, the Content-Disposition header (filename and filename*), and <a download> all carry the same file name. Put it inside renderUI(): it is registered again on each redraw, the URL changes with it, and you never get a stale file.

Usage

kit_download_button(
  session,
  id,
  label,
  filename,
  content,
  class = NULL,
  app = getOption("kitDesign.app", "kit")
)

Arguments

session

The module's session (the namespace is added to the id automatically).

id

The button id (without namespace).

label

The button text, e.g. "下載 CSV" ("Download CSV").

filename

The download file name (a string; may contain Chinese and spaces).

content

function(file): writes the file to file.

class

An extra class, e.g. kit_btn_class("secondary"), "btn-primary".

app

The app name: used in log messages; when the file name is all Chinese, the ASCII fallback name for old browsers is its lowercase form ("第一波.csv" → "kitjoin.csv"). Defaults to getOption("kitDesign.app", "kit"): the app sets it once in .onLoad().

Value

<button type="button" class="btn btn-default kit-download" data-kit-href="網址" data-kit-download="檔名"> (data-kit-href is the download URL, data-kit-download the file name).

Details

The file is written only when the user clicks download (content(file), which can read reactives). If writing fails: the error goes to the log (" 下載失敗(檔名):…", " download failed (file name): …"), this session shows a red notification (which does not disappear on its own), and the response is 500 with the same sentence. Messages from kit_abort() are shown to the user as written; other errors do not expose internal messages.

The button is a <button>, not a link: the URL and the file name are in data-kit-href and data-kit-download, and kit.js (loaded by use_kit()) fetches the file in the background and saves it, so the page never leaves. Browser extensions that take over links on the page (some "document viewer" add-ons do, and the download then fails with "Not Found") find nothing to take.

Content-Type follows the extension: .csv, .zip, and .html get their own MIME types; everything else (.sav, .csv.gz) is application/octet-stream, so browsers that add an extension based on MIME type don't add an extra one.

See also

Examples

if (interactive()) {
  server <- function(input, output, session) {
    output$dl_ui <- shiny::renderUI(kit_download_button(
      session, "dl", "下載 CSV", "第一波 資料.csv",   # "Download CSV", "Wave 1 data.csv"
      function(file) utils::write.csv(mtcars, file)
    ))
  }
}