9

I came across this snippet for uploading files in Jupyter however I don't know how to save this file on the machine that executes the code or how to show the first 5 lines of the uploaded file. Basically I am looking for proper commands for accessing the file after it has been uploaded:

import io
from IPython.display import display
import fileupload

def _upload():

    _upload_widget = fileupload.FileUploadWidget()

    def _cb(change):
        decoded = io.StringIO(change['owner'].data.decode('utf-8'))
        filename = change['owner'].filename
        print('Uploaded `{}` ({:.2f} kB)'.format(
            filename, len(decoded.read()) / 2 **10))

    _upload_widget.observe(_cb, names='data')
    display(_upload_widget)

_upload()
Thomas K
  • 39,200
  • 7
  • 84
  • 86
Mona Jalal
  • 34,860
  • 64
  • 239
  • 408
  • The `_cb` function is what gets called when the file is uploaded. In the example, it doesn't store the data anywhere, so it's only accessible outside the function. You could store it in a global variable to make it accessible to code later on. – Thomas K Sep 14 '16 at 20:48

5 Answers5

8

_cb is called when the upload finishes. As described in the comment above, you can write to a file there, or store it in a variable. For example:

from IPython.display import display
import fileupload

uploader = fileupload.FileUploadWidget()

def _handle_upload(change):
    w = change['owner']
    with open(w.filename, 'wb') as f:
        f.write(w.data)
    print('Uploaded `{}` ({:.2f} kB)'.format(
        w.filename, len(w.data) / 2**10))

uploader.observe(_handle_upload, names='data')

display(uploader)

After the upload has finished, you can access the filename as:

uploader.filename
minrk
  • 37,545
  • 9
  • 92
  • 87
  • 1
    fileupload is deprecated, the new way is `from ipywidgets import FileUpload` However, with nearly no documentation so far and the syntax is pretty much the same – Max Apr 28 '20 at 09:55
4

I am working on ML with Jupyter notebook, and I was looking for a solution to select the local files containing the datasets by browsing amongst the local file system. Although, the question here refers more to uploading than selecting a file. I am putting here a snippet that I found here because when I was looking for a solution for my particular case, the result of the search took me several times to here.

import os
import ipywidgets as widgets

class FileBrowser(object):
    def __init__(self):
        self.path = os.getcwd()
        self._update_files()

    def _update_files(self):
        self.files = list()
        self.dirs = list()
        if(os.path.isdir(self.path)):
            for f in os.listdir(self.path):
                ff = os.path.join(self.path, f)
                if os.path.isdir(ff):
                    self.dirs.append(f)
                else:
                    self.files.append(f)

    def widget(self):
        box = widgets.VBox()
        self._update(box)
        return box

    def _update(self, box):

        def on_click(b):
            if b.description == '..':
                self.path = os.path.split(self.path)[0]
            else:
                self.path = os.path.join(self.path, b.description)
            self._update_files()
            self._update(box)

        buttons = []
        if self.files:
            button = widgets.Button(description='..', background_color='#d0d0ff')
            button.on_click(on_click)
            buttons.append(button)
        for f in self.dirs:
            button = widgets.Button(description=f, background_color='#d0d0ff')
            button.on_click(on_click)
            buttons.append(button)
        for f in self.files:
            button = widgets.Button(description=f)
            button.on_click(on_click)
            buttons.append(button)
        box.children = tuple([widgets.HTML("<h2>%s</h2>" % (self.path,))] + buttons)

And to use it:

f = FileBrowser()
f.widget()
#   <interact with widget, select a path>
# in a separate cell:
f.path # returns the selected path
Rodolfo Alvarez
  • 972
  • 2
  • 10
  • 18
3

4 years later this remains an interesting question, though Fileupload has slightly changed and belongs to ipywidgets....

Here is some demo that shows how to get the file/files after the button click and reset the button to get more files....

from ipywidgets import FileUpload

def on_upload_change(change):
    if not change.new:
        return
    up = change.owner
    for filename,data in up.value.items():
        print(f'writing [{filename}] to ./')
        with open(filename, 'wb') as f:
            f.write(data['content'])
    up.value.clear()
    up._counter = 0

upload_btn = FileUpload()
upload_btn.observe(on_upload_change, names='_counter')
upload_btn

And here is a "debug" version that shows what is going on / why things work...

from ipywidgets import FileUpload

def on_upload_change(change):
    if change.new==0:
        print ('cleared')
        return
    up = change.owner
    print (type(up.value))
    for filename,data in up.value.items():
        print('==========================================================================================')
        print(filename)
        for k,v in data['metadata'].items():
            print(f'    -{k:13}:[{v}]')
        print(f'    -content len  :[{len(data["content"])}]')
        print('==========================================================================================')
    up.value.clear()
    up._counter = 0

upload_btn = FileUpload()
upload_btn.observe(on_upload_change, names='_counter')
upload_btn
ntg
  • 12,950
  • 7
  • 74
  • 95
1

I stumbled into this thread ~2 years late. For those still confused about how to work with the fileupload widget I have built off of the excellent answer posted by minrk with some other usage examples below.

from IPython.display import display
import fileupload

uploader = fileupload.FileUploadWidget()

def _handle_upload(change):
    w = change['owner']
    with open(w.filename, 'wb') as f:
        f.write(w.data)
    print('Uploaded `{}` ({:.2f} kB)'.format(
        w.filename, len(w.data) / 2**10))

uploader.observe(_handle_upload, names='data')

display(uploader)

From the widget documentation:

class FileUploadWidget(ipywidgets.DOMWidget):
    '''File Upload Widget.
    This widget provides file upload using `FileReader`.
    '''
    _view_name = traitlets.Unicode('FileUploadView').tag(sync=True)
    _view_module = traitlets.Unicode('fileupload').tag(sync=True)

    label = traitlets.Unicode(help='Label on button.').tag(sync=True)
    filename = traitlets.Unicode(help='Filename of `data`.').tag(sync=True)
    data_base64 = traitlets.Unicode(help='File content, base64 encoded.'
                                    ).tag(sync=True)
    data = traitlets.Bytes(help='File content.')

    def __init__(self, label="Browse", *args, **kwargs):
        super(FileUploadWidget, self).__init__(*args, **kwargs)
        self._dom_classes += ('widget_item', 'btn-group')
        self.label = label

    def _data_base64_changed(self, *args):
        self.data = base64.b64decode(self.data_base64.split(',', 1)[1])

Get the data in bytestring format:

uploader.data

Get the data in a regular utf-8 string:

datastr= str(uploader.data,'utf-8')

Make a new pandas dataframe from the utf-8 string (e.g. from a .csv input):

import pandas as pd
from io import StringIO

datatbl = StringIO(datastr)
newdf = pd.read_table(datatbl,sep=',',index_col=None)

0

You have to enable the file upload option in your code, to enable the browse button to appear in your notebook. Run the following !jupyter nbextension enable fileupload --user --py