MCPcopy Create free account
hub / github.com/datapane/datapane / FileUpload

Class FileUpload

python-client/src/datapane/_vendor/bottle.py:2730–2794  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2728
2729
2730class FileUpload(object):
2731 def __init__(self, fileobj, name, filename, headers=None):
2732 """ Wrapper for file uploads. """
2733 #: Open file(-like) object (BytesIO buffer or temporary file)
2734 self.file = fileobj
2735 #: Name of the upload form field
2736 self.name = name
2737 #: Raw filename as sent by the client (may contain unsafe characters)
2738 self.raw_filename = filename
2739 #: A :class:`HeaderDict` with additional headers (e.g. content-type)
2740 self.headers = HeaderDict(headers) if headers else HeaderDict()
2741
2742 content_type = HeaderProperty('Content-Type')
2743 content_length = HeaderProperty('Content-Length', reader=int, default=-1)
2744
2745 def get_header(self, name, default=None):
2746 """ Return the value of a header within the multipart part. """
2747 return self.headers.get(name, default)
2748
2749 @cached_property
2750 def filename(self):
2751 """ Name of the file on the client file system, but normalized to ensure
2752 file system compatibility. An empty filename is returned as 'empty'.
2753
2754 Only ASCII letters, digits, dashes, underscores and dots are
2755 allowed in the final filename. Accents are removed, if possible.
2756 Whitespace is replaced by a single dash. Leading or tailing dots
2757 or dashes are removed. The filename is limited to 255 characters.
2758 """
2759 fname = self.raw_filename
2760 if not isinstance(fname, unicode):
2761 fname = fname.decode('utf8', 'ignore')
2762 fname = normalize('NFKD', fname)
2763 fname = fname.encode('ASCII', 'ignore').decode('ASCII')
2764 fname = os.path.basename(fname.replace('\\', os.path.sep))
2765 fname = re.sub(r'[^a-zA-Z0-9-_.\s]', '', fname).strip()
2766 fname = re.sub(r'[-\s]+', '-', fname).strip('.-')
2767 return fname[:255] or 'empty'
2768
2769 def _copy_file(self, fp, chunk_size=2 ** 16):
2770 read, write, offset = self.file.read, fp.write, self.file.tell()
2771 while 1:
2772 buf = read(chunk_size)
2773 if not buf: break
2774 write(buf)
2775 self.file.seek(offset)
2776
2777 def save(self, destination, overwrite=False, chunk_size=2 ** 16):
2778 """ Save file to disk or copy its content to an open file(-like) object.
2779 If *destination* is a directory, :attr:`filename` is added to the
2780 path. Existing files are not overwritten by default (IOError).
2781
2782 :param destination: File path, directory or file(-like) object.
2783 :param overwrite: If True, replace existing files. (default: False)
2784 :param chunk_size: Bytes to read at a time. (default: 64kb)
2785 """
2786 if isinstance(destination, basestring): # Except file-likes here
2787 if os.path.isdir(destination):

Callers 1

POSTMethod · 0.85

Calls 1

HeaderPropertyClass · 0.85

Tested by

no test coverage detected