def upload_files(self, source_paths, dir_name=None):
def scan_folders(folder_path):<EOL><INDENT>file_list = os.listdir(folder_path)<EOL>source_paths = [os.path.join(folder_path, f) for f in file_list]<EOL>self.upload_files(source_paths,<EOL>os.path.join(dir_name, os.path.split(folder_path)[<NUM_LIT:1>]))<EOL><DEDENT>self.check_first()<EOL>if not dir_name:<EOL><INDENT>folder_dialog = FolderBrowserDialog(self, self.app)<EOL>response = folder_dialog.run()<EOL>if response != Gtk.ResponseType.OK:<EOL><INDENT>folder_dialog.destroy()<EOL>return<EOL><DEDENT>dir_name = folder_dialog.get_path()<EOL>folder_dialog.destroy()<EOL><DEDENT>invalid_paths = []<EOL>for source_path in source_paths:<EOL><INDENT>if util.validate_pathname(source_path) != ValidatePathState.OK:<EOL><INDENT>invalid_paths.append(source_path)<EOL>continue<EOL><DEDENT>if (os.path.split(source_path)[<NUM_LIT:1>].startswith('<STR_LIT:.>') and<EOL>not self.app.profile['<STR_LIT>']):<EOL><INDENT>continue<EOL><DEDENT>if os.path.isfile(source_path):<EOL><INDENT>self.upload_file(source_path, dir_name)<EOL><DEDENT>elif os.path.isdir(source_path):<EOL><INDENT>scan_folders(source_path)<EOL><DEDENT><DEDENT>self.app.blink_page(self)<EOL>self.scan_tasks()<EOL>if not invalid_paths:<EOL><INDENT>return<EOL><DEDENT>dialog = Gtk.Dialog(_('<STR_LIT>'), self.app.window,<EOL>Gtk.DialogFlags.MODAL,<EOL>(Gtk.STOCK_CLOSE, Gtk.ResponseType.OK))<EOL>dialog.set_default_size(<NUM_LIT>, <NUM_LIT>)<EOL>dialog.set_border_width(<NUM_LIT:10>)<EOL>box = dialog.get_content_area()<EOL>scrolled_window = Gtk.ScrolledWindow()<EOL>box.pack_start(scrolled_window, True, True, <NUM_LIT:0>)<EOL>text_buffer = Gtk.TextBuffer()<EOL>textview = Gtk.TextView.new_with_buffer(text_buffer)<EOL>scrolled_window.add(textview)<EOL>for invalid_path in invalid_paths:<EOL><INDENT>text_buffer.insert_at_cursor(invalid_path)<EOL>text_buffer.insert_at_cursor('<STR_LIT:\n>')<EOL><DEDENT>infobar = Gtk.InfoBar()<EOL>infobar.set_message_type(Gtk.MessageType.ERROR)<EOL>box.pack_end(infobar, False, False, <NUM_LIT:0>)<EOL>info_label= Gtk.Label()<EOL>infobar.get_content_area().pack_start(info_label, False, False, <NUM_LIT:0>)<EOL>info_label.set_label('<STR_LIT>'.join([<EOL>'<STR_LIT>', ValidatePathStateText[<NUM_LIT:1>], '<STR_LIT:\n>',<EOL>'<STR_LIT>', ValidatePathStateText[<NUM_LIT:2>], '<STR_LIT:\n>',<EOL>'<STR_LIT>', ValidatePathStateText[<NUM_LIT:3>], '<STR_LIT:\n>',<EOL>]))<EOL>box.show_all()<EOL>dialog.run()<EOL>dialog.destroy()<EOL>
批量创建上传任务, 会扫描子目录并依次上传.

        source_path - 本地文件的绝对路径
        dir_name    - 文件在服务器上的父目录, 如果为None的话, 会弹出一个
                      对话框让用户来选择一个目录.