You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shiny应用中渲染TIFF文件(PNG转换方案失效)

解决Shiny中TIFF图片上传渲染的错误问题

你的错误根源确实是inFile$datapath <- readPNG("test.png")这行代码:readPNG()返回的是多维像素数组(对应图片的像素矩阵),而inFile$datapath原本是字符串类型的文件路径,强行将数组赋值给字符串字段,会触发数据结构不匹配的错误。

修正方案1:保留本地文件转换逻辑

直接使用生成的PNG文件路径生成dataURI,不需要修改inFile对象:

library(pacman)
pacman::p_load(shiny,shinydashboard,base64enc,tiff,png,xfun,tidyverse)

#Header
header <-  dashboardHeader(title = "Visualization Tool")

#sidebar
sidebar <- dashboardSidebar(
  sidebarMenu(
    menuItem("1",tabName = "iris", icon = icon("magnifying-glass")),
    menuItem("2",tabName = "cars", icon = icon("fill")),
    menuItem("3",tabName = "test", icon = icon("puzzle-piece"))
  )
)

#body
body <- dashboardBody(
  tabItems(
    tabItem("cars",
            fluidPage(
              h1("Cars"),
              fileInput("upload","Upload image", accept=c("image/png","image/tif", "image/tiff")),
              uiOutput("image")
            )
    )
  )
)

ui <- dashboardPage(header, sidebar, body)

server <- function(input,output){

  tiff_image <- reactive({
    inFile <- input[["upload"]]
    if(!is.null(inFile$datapath)){
      file_ext <- xfun::file_ext(inFile$datapath)
      if(file_ext %in% c("tif", "tiff")){
        # 读取TIFF并转为PNG
        tiff_img <- tiff::readTIFF(inFile$datapath, native=FALSE)
        # 使用临时文件避免覆盖
        temp_png <- tempfile(fileext = ".png")
        png::writePNG(tiff_img, temp_png)
        # 直接用临时PNG文件生成dataURI
        base64enc::dataURI(file = temp_png, mime = "image/png")
      } else {
        # 非TIFF文件直接生成dataURI
        base64enc::dataURI(file = inFile$datapath, mime = paste0("image/", file_ext))
      }
    }
  })
  
  output[["image"]] <- renderUI({
    req(tiff_image())
    tags$div(
      tags$img(src= tiff_image(), width="100%"),
      style = "width: 400px;"
    )
  })
}

shinyApp(ui, server)

关键修改点:

  • 用tempfile()生成临时PNG文件,避免多次上传时覆盖同一个文件
  • 直接使用临时PNG的路径生成dataURI,不再修改inFile对象
  • 扩展支持.tiff后缀,同时根据文件后缀动态设置mime类型

优化方案2:内存中直接转换(无需本地文件)

可以跳过本地文件存储,直接在内存中完成TIFF到PNG的转换,更高效:

server <- function(input,output){

  tiff_image <- reactive({
    inFile <- input[["upload"]]
    req(inFile$datapath)
    
    file_ext <- xfun::file_ext(inFile$datapath)
    if(file_ext %in% c("tif", "tiff")){
      tiff_img <- tiff::readTIFF(inFile$datapath, native=FALSE)
      # 创建内存连接
      conn <- rawConnection(raw(0), "w")
      png::writePNG(tiff_img, conn)
      # 获取内存中的PNG数据并转base64
      png_raw <- rawConnectionValue(conn)
      close(conn)
      base64enc::dataURI(data = png_raw, mime = "image/png")
    } else {
      base64enc::dataURI(file = inFile$datapath, mime = paste0("image/", file_ext))
    }
  })
  
  output[["image"]] <- renderUI({
    req(tiff_image())
    tags$div(
      tags$img(src= tiff_image(), width="100%"),
      style = "width: 400px;"
    )
  })
}

这种方式不需要生成本地临时文件,适合频繁上传的场景,减少磁盘IO操作。

内容的提问来源于stack exchange,提问作者user214476

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:07:48