2017-02-08 19 views
2

Я создаю блестящее приложение, которое позволяет пользователям загружать изображения на сервер. Я хотел бы отобразить изображение на экране, не загружая его сначала, а затем возвращать полученный результат. Это возможно?Render образ перед загрузкой в ​​Shiny

Это мой код прямо сейчас. Вы можете выбрать файл изображения, который будет загружен. Затем изображение выводится из файла на стороне сервера после его получения. Я бы хотел избежать поездки туда и обратно.

UI

fluidPage(
    titlePanel("File upload"), 
    sidebarLayout(
     sidebarPanel(
      fileInput("img", "Choose image file", 
       accept=c("image/jpeg", "image/x-windows-bmp")) 
     ), 
     mainPanel(
      imageOutput("picture", width="500px", height="500px") 
     ) 
    ) 
) 

Сервер

function(input, output, session) 
{ 
    output$picture <- renderImage({ 
     imgFile <- input$img 
     if(is.null(imgFile)) 
      return(list(src="")) 
     list(src=imgFile$datapath, alt=imgFile$name, contentType=imgFile$type) 
    }, deleteFile=FALSE) 

    # do more stuff with the file 
} 
+0

Я не уверен, что я понимаю вопрос. Файл находится на компьютере вашего пользователя, а не на вашем сервере, и вы хотите отображать его без загрузки? Есть ли опция загрузки снаружи, и вы знаете путь? – BigDataScientist

+0

Я хочу загрузить файл, но я также хочу отобразить его, не дожидаясь, пока сервер вернется ко мне. Я делаю некоторые серверные вычисления, которые могут занять некоторое время, поэтому было бы неплохо отобразить изображение сразу. –

ответ

1

Редактировать: Хорошо, я теперь вопрос для меня я надеюсь, я надеюсь :). Проблема заключается в том, что фотографии добавляются в пределах <output id="list"></output>. Поэтому я предлагаю очистить его до того, как будет добавлена ​​новая картинка: document.getElementById('list').innerHTML = ''

library(shiny) 
library(shinyjs) 
shinyApp(ui = fluidPage(
    useShinyjs(), 
    titlePanel("File upload"), 
    sidebarLayout(
    sidebarPanel(
     fileInput("img", "Choose image file", 
       accept=c("image/jpeg", "image/x-windows-bmp")) 
    ), 
    mainPanel(
     HTML('<output id="list"></output>') 
    ) 
)), 
    server = function(input, output, session){ 
    shinyjs::runjs(" 

        function handleFileSelect(evt) { 
        document.getElementById('list').innerHTML = '' 
        var files = evt.target.files; // FileList object 
        // Loop through the FileList and render image files as thumbnails. 
        for (var i = 0, f; f = files[i]; i++) { 

        // Only process image files. 
        if (!f.type.match('image.*')) { 
        continue; 
        } 

        var reader = new FileReader(); 

        // Closure to capture the file information. 
        reader.onload = (function(theFile) { 
        return function(e) { 
        // Render thumbnail. 
        var span = document.createElement('span'); 
        span.innerHTML = ['<img class=\"thumb\" src=\"', e.target.result, 
        '\" title=\"', escape(theFile.name), '\"/>'].join(''); 
        document.getElementById('list').insertBefore(span, null); 
        }; 
        })(f); 

        // Read in the image file as a data URL. 
        reader.readAsDataURL(f); 
        } 
        } 
        document.getElementById('img').addEventListener('change', handleFileSelect, false);") 

    }) 
+0

Нет, это тоже не работает ... –

+0

Кстати, чтобы устранить проблему с файлами, появляющимися дважды, удалите бит renderImage/imageOutput. –

+0

Я смущен. Когда я запускаю приведенный выше код и загружаю несколько раз, я не вижу никаких изображений на боковой панели и одного изображения на главной панели, а именно: я загрузил последний (в Firefox и Chrome) ..... – BigDataScientist

3

Вы можете использовать пакет shinyjs для вызова FileReader из HTML 5 read here

library(shinyjs) 
shinyApp(ui = fluidPage(
    useShinyjs(), 
    titlePanel("File upload"), 
    sidebarLayout(
    sidebarPanel(
     fileInput("img", "Choose image file", 
       accept=c("image/jpeg", "image/x-windows-bmp")), 
     HTML('<output id="list"></output>') 
    ), 
    mainPanel(
     imageOutput("picture", width="500px", height="500px") 
    ) 
)), 
server = function(input, output, session){ 
    shinyjs::runjs(" 

    function handleFileSelect(evt) { 
    var files = evt.target.files; // FileList object 
    // Loop through the FileList and render image files as thumbnails. 
    for (var i = 0, f; f = files[i]; i++) { 

    // Only process image files. 
    if (!f.type.match('image.*')) { 
    continue; 
    } 

    var reader = new FileReader(); 

    // Closure to capture the file information. 
    reader.onload = (function(theFile) { 
    return function(e) { 
    // Render thumbnail. 
    var span = document.createElement('span'); 
    span.innerHTML = ['<img class=\"thumb\" src=\"', e.target.result, 
    '\" title=\"', escape(theFile.name), '\"/>'].join(''); 
    document.getElementById('list').insertBefore(span, null); 
    }; 
    })(f); 

    // Read in the image file as a data URL. 
    reader.readAsDataURL(f); 
    } 
    } 
    document.getElementById('img').addEventListener('change', handleFileSelect, false);") 

    output$picture <- renderImage({ 
    imgFile <- input$img 
    if(is.null(imgFile)) 
     return(list(src="")) 
    list(src=imgFile$datapath, alt=imgFile$name, contentType=imgFile$type) 
    }, deleteFile=FALSE) 
}) 
+0

Это довольно круто, но я столкнулся с несколькими проблемами. Во-первых, изображение, созданное JS, появляется на боковой панели, где я хочу, чтобы изображение было заменено на главной панели. Кроме того, если я использую управление загрузкой более одного раза, изображение боковой панели не стирается. Вместо этого каждое новое изображение отображается ниже того, которое было ранее. –

+0

Я могу исправить первую проблему, поместив элемент 'HTML()' в основную панель, но я не уверен, как исправить вторую. –