API google drive
Google drive создать папку на общем диске
Подскажите пожалуйста как создать папку на общем диске google drive. Как папки создавать знаю, id.
Облако из слов. Подключение файлов с Google Drive в Colab
!pip install wordcloud from os import path from PIL import Image import numpy as np import.
Работа с Google Drive
Мне нужно организовать работу с Google диском. Я пробовал и через различные модули(gdata, pydrive).
Python + Google Drive + PostgreSQL
Здравствуйте. Есть ли образец скрипта на Python, благодаря которому можно скачать csv-файлы с.
Автоматизируй это!
![]()
7054 / 4559 / 1207
Регистрация: 30.03.2015
Сообщений: 13,132
Записей в блоге: 29

Сообщение было отмечено hasker2 как решение
Решение
40 / 42 / 16
Регистрация: 15.01.2021
Сообщений: 432
![]()
5416 / 3840 / 1214
Регистрация: 28.10.2013
Сообщений: 9,554
Записей в блоге: 1

Сообщение было отмечено hasker2 как решение
Решение
hasker2,
И ты тоже не читал правила форума?
Темы не удаляются.
Ты можешь закрыть тему сам предоставив ответ (и нажать кнопку лучший ответ) — сделай что-нить полезное на этом форуме.
40 / 42 / 16
Регистрация: 15.01.2021
Сообщений: 432
проглядел тот пункт(
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Google API
Подскажите пожалуйста. Решил разобраться как работать с гугл диском, нашел ответ, через API. Создал.
Google api
Здравствуйте, есть задача, выгрузить все файлы с расширением .doc и .docx из гугл диска и.
Google Sheets API
Добрый день, возник вопрос по гугл шитс апи) Необходимо сделать POST-запрос, при этом надо, чтобы.
Функции для работы с Google Drive API v3 через REST API в C++ Builder
Выкладываю функции для работы с Google Drive API v3 через REST API в C++ Builder, так-как в.
При загрузки файла на Google drive из своего приложения через Google Api как указать каталог?
Пишу софтину которая должна через промежутки времени сохранять определенные логи на Google Drive.
Google drive API
Дрброго времени суток. Хотел спросить может кто то задавался тоже подобным вопросом. Суть вопроса.
Пишем скрипт для синхронизации папок с Google Drive, плюс учимся использовать Google Drive API

В этой статье мы рассмотрим основные инструменты работы с Google Drive REST API, осуществим «прямую» и «обратную» синхронизацию папки на компьютере с папкой в облаке Гугл Диска, а заодно выясним какие сложности могут возникнуть при работе с Google Docs через API Диска и как правильно их импортировать и экспортировать чтобы (почти) никто не пострадал.
Лирическое вступление
Однажды, проснувшись ранним утром, я внезапно обнаружил недостаток продуктивности (и автоматизированности) в повседневной жизни. Первой «под нож оптимизации» попала рабочая папка с полезными книжками, проектами, документами и смешными картинками котов. Обычно вся моя бурная деятельность происходит за домашним компьютером, однако иногда требуется действовать вне пределов уютной комнаты, и хочется чтобы все привычное было под рукой, в том числе и текущие проекты. В таких случаях на помощь приходят на помощь флешки, но это прошлый век и не стильно, хочется чтобы все было надежно доступно в любой момент из облака (при наличии интернета конечно). Как пример такого облака в данном случае будет Гугл Диск.
Но поскольку каждый день происходят изменения, что-то добавляется, что-то улетает в корзину, и вручную следить за этим нет никакого желания, должна быть настроена синхронизация. На Windows и MacOS есть специальный софт примерно для таких целей. Я большую часть времени провожу за Ubuntu, и официального клиента под линукс нет и не предвидится. Да и вообще это не кажется очень удобным. Хочется иметь универсальный метод решения данной задачи, желательно кроссплатформенный, без перекидывания всех файлов в специальную папку. Поиск готовых решений ни к чему не привел, ни один вариант меня полностью не устроил. Я решил что лучше всего будет самостоятельно написать скрипт на Python и повесить его к cron (или запускать самостоятельно и вручную). К тому же на хабре при беглом поиске не нашлось туториалов по этой теме, так что может в дальнейшем кому-то и пригодится.
Получаем необходимые данные («включаем» Drive API и получаем необходимые ключи)
Выполнив несколько простых шагов, уже через 5 минут у Вас в руках уже будет тестовое приложение с доступом к Drive API.
Перед началом захватывающего путешествия, убедитесь что взяли с собой:
- Python версии 2.6 или выше (в моем случае это был Python 3 чего и Вам советую).
- Пакетный менеджер pip.
- Доступ к интернету и веб-браузер.
- Аккаунт Google и рабочий Google Drive.
К этому нужно отнестись с полной серьезностью, потому что если хотя бы одно из этих условий будет нарушено, дальше ничего не получится.
Порядок действий примерно такой:
1) Переходим по ссылке для того чтобы создать наш проект и автоматически включить Drive API. Жмем Continue, затем Go to credentials
2) На странице Add cridentials to your page жмём кнопку Cancel.
3) На странице выбираем вкладку OAuth consent screen. Выбираем нужный Email и вписываем Product name, жмем Save.
4) Во вкладе Credentials выбираем Create credentials, затем Oauth client ID.
5) Выбираем тип Other, вписываем звучное название и жмем Create.
6) В поле нашего «проекта» жмем по кнопке справа для скачивания json файла. Сохраняем его в папку с будущим скриптом, для удобства переименуем в client_secret.json
Весь процесс в картинках для наглядности

Далее выполняем действия уже на компьютере
1 — Устанавливаем зависимости
Установим Google Client Library библиотеку
sudo pip install --upgrade google-api-python-client
Или посмотрите по ссылке если возникли вопросы.
2 — Создадим наш начальный скрипт
Создаем python скрипт рядом с сорханённым .json файлом и сохраняем пример кода для теста:
Исходный код
from __future__ import print_function import httplib2 import os from apiclient import discovery from oauth2client import client from oauth2client import tools from oauth2client.file import Storage try: import argparse flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() except ImportError: flags = None # If modifying these scopes, delete your previously saved credentials # at ~/.credentials/drive-python-quickstart.json SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly' CLIENT_SECRET_FILE = 'client_secret.json' APPLICATION_NAME = 'Drive API Python Quickstart' def get_credentials(): home_dir = os.path.expanduser('~') credential_dir = os.path.join(home_dir, '.credentials') if not os.path.exists(credential_dir): os.makedirs(credential_dir) credential_path = os.path.join(credential_dir, 'drive-python-quickstart.json') store = Storage(credential_path) credentials = store.get() if not credentials or credentials.invalid: flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) flow.user_agent = APPLICATION_NAME if flags: credentials = tools.run_flow(flow, store, flags) else: # Needed only for compatibility with Python 2.6 credentials = tools.run(flow, store) print('Storing credentials to ' + credential_path) return credentials def main(): credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('drive', 'v3', http=http) results = service.files().list( pageSize=10,fields="nextPageToken, files(id, name)").execute() items = results.get('files', []) if not items: print('No files found.') else: print('Files:') for item in items: print(' ()'.format(item['name'], item['id'])) if __name__ == '__main__': main()
При первом запуске он попробует открыть вкладку в браузере и попросит залогиниться в гугл аккаунте и согласиться с выдаваемыми правами.
В целом там все просто и понятно, но если вкратце пробежаться
- функция get_credentials создает/достает .json файл полномочий для авторизации через API.
- scopes это наши права доступа (в дальнейшем поставим самые большие ведь себе доверяем)
- service создает нам доступ к аккаунту Google Drive
- дальше обращение к апи, берем список файлов (ограничиваемся 10 штуками) и выводим данные.
Можно даже запустить и посмотреть на то как он выведет имена и id первых десяти файлов и папок в корневой директории.
Вообще, это почти полный coypaste из официального quickstart-туториала, так что если возникнут проблемы посмотрите там.
Немного про Google Drive API

Собственно давайте знакомиться с API ближе.
Структура Drive REST API представляет из себя набор «ресурсов» (ориг. resources types), у каждого из которых есть свои методы.
Всего из интересных это «ресурсы» about(), files() и возможно comments(). Все остальные можно посмотреть, опять же, в документации, и если они вам нужны то работа c ними будет аналогичной (скорее всего). Мы же рассмотрим действительно полезные вещи.
В первую очередь для затравки посмотрим что мы сможем узнать о нашем Диске через методы about() (что логично). Благо здесь все просто и имеется только один метод get().
about_example = drive_service.about(fields='user, storageQuota, exportFormats, importFormats').get('')
Параметров здесь много, расскажу о тех которые мне показались важными или интересными.
Параметры importFormats и exportFormats содержат информацию, в какие форматы можно перевести файл при его загрузке и скачивании соответственно. Это информация может быть важной в случае работы с файлами формата Google Docs, об этом чуть ниже.
StorageQuota может поведать, что логично, о количестве использованного и оставшегося свободного пространства в облаке.
user содержит несколько полей, например displayName, photoLink и emailAddress (значения понятны из названия)
На выходе получим JSON структуру с этими данными.
Пример ответа, включая exportFormats и importFormats
«user»: «kind»: «drive#user»,
«displayName»: «Имя Фамилия»,
«photoLink»: «http://i.imgur.com/hgXLjzr.png»,
«me»: true,
«permissionId»: «id number»,
«emailAddress»: «youremail@gmail.com»
>,
«storageQuota»: «limit»: «16106127360»,
«usage»: «2920407530»,
«usageInDrive»: «1590570002»,
«usageInDriveTrash»: «54316729»
>,
«importFormats»: «application/x-vnd.oasis.opendocument.presentation»: [
«application/vnd.google-apps.presentation»
],
«text/tab-separated-values»: [
«application/vnd.google-apps.spreadsheet»
],
«image/jpeg»: [
«application/vnd.google-apps.document»
],
«image/bmp»: [
«application/vnd.google-apps.document»
],
«image/gif»: [
«application/vnd.google-apps.document»
],
«application/vnd.ms-excel.sheet.macroenabled.12»: [
«application/vnd.google-apps.spreadsheet»
],
«application/vnd.openxmlformats-officedocument.wordprocessingml.template»: [
«application/vnd.google-apps.document»
],
«application/vnd.ms-powerpoint.presentation.macroenabled.12»: [
«application/vnd.google-apps.presentation»
],
«application/vnd.ms-word.template.macroenabled.12»: [
«application/vnd.google-apps.document»
],
«application/vnd.openxmlformats-officedocument.wordprocessingml.document»: [
«application/vnd.google-apps.document»
],
«image/pjpeg»: [
«application/vnd.google-apps.document»
],
«application/vnd.google-apps.script+text/plain»: [
«application/vnd.google-apps.script»
],
«application/vnd.ms-excel»: [
«application/vnd.google-apps.spreadsheet»
],
«application/vnd.sun.xml.writer»: [
«application/vnd.google-apps.document»
],
«application/vnd.ms-word.document.macroenabled.12»: [
«application/vnd.google-apps.document»
],
«application/vnd.ms-powerpoint.slideshow.macroenabled.12»: [
«application/vnd.google-apps.presentation»
],
«text/rtf»: [
«application/vnd.google-apps.document»
],
«text/plain»: [
«application/vnd.google-apps.document»
],
«application/vnd.oasis.opendocument.spreadsheet»: [
«application/vnd.google-apps.spreadsheet»
],
«application/x-vnd.oasis.opendocument.spreadsheet»: [
«application/vnd.google-apps.spreadsheet»
],
«image/png»: [
«application/vnd.google-apps.document»
],
«application/x-vnd.oasis.opendocument.text»: [
«application/vnd.google-apps.document»
],
«application/msword»: [
«application/vnd.google-apps.document»
],
«application/pdf»: [
«application/vnd.google-apps.document»
],
«application/json»: [
«application/vnd.google-apps.script»
],
«application/x-msmetafile»: [
«application/vnd.google-apps.drawing»
],
«application/vnd.openxmlformats-officedocument.spreadsheetml.template»: [
«application/vnd.google-apps.spreadsheet»
],
«application/vnd.ms-powerpoint»: [
«application/vnd.google-apps.presentation»
],
«application/vnd.ms-excel.template.macroenabled.12»: [
«application/vnd.google-apps.spreadsheet»
],
«image/x-bmp»: [
«application/vnd.google-apps.document»
],
«application/rtf»: [
«application/vnd.google-apps.document»
],
«application/vnd.openxmlformats-officedocument.presentationml.template»: [
«application/vnd.google-apps.presentation»
],
«image/x-png»: [
«application/vnd.google-apps.document»
],
«text/html»: [
«application/vnd.google-apps.document»
],
«application/vnd.oasis.opendocument.text»: [
«application/vnd.google-apps.document»
],
«application/vnd.openxmlformats-officedocument.presentationml.presentation»: [
«application/vnd.google-apps.presentation»
],
«application/vnd.openxmlformats-officedocument.spreadsheetml.sheet»: [
«application/vnd.google-apps.spreadsheet»
],
«application/vnd.google-apps.script+json»: [
«application/vnd.google-apps.script»
],
«application/vnd.openxmlformats-officedocument.presentationml.slideshow»: [
«application/vnd.google-apps.presentation»
],
«application/vnd.ms-powerpoint.template.macroenabled.12»: [
«application/vnd.google-apps.presentation»
],
«text/csv»: [
«application/vnd.google-apps.spreadsheet»
],
«application/vnd.oasis.opendocument.presentation»: [
«application/vnd.google-apps.presentation»
],
«image/jpg»: [
«application/vnd.google-apps.document»
],
«text/richtext»: [
«application/vnd.google-apps.document»
]
>,
«exportFormats»: «application/vnd.google-apps.form»: [
«application/zip»
],
«application/vnd.google-apps.document»: [
«application/rtf»,
«application/vnd.oasis.opendocument.text»,
«text/html»,
«application/pdf»,
«application/epub+zip»,
«application/zip»,
«application/vnd.openxmlformats-officedocument.wordprocessingml.document»,
«text/plain»
],
«application/vnd.google-apps.drawing»: [
«image/svg+xml»,
«image/png»,
«application/pdf»,
«image/jpeg»
],
«application/vnd.google-apps.spreadsheet»: [
«application/x-vnd.oasis.opendocument.spreadsheet»,
«text/tab-separated-values»,
«application/pdf»,
«application/vnd.openxmlformats-officedocument.spreadsheetml.sheet»,
«text/csv»,
«application/zip»,
«application/vnd.oasis.opendocument.spreadsheet»
],
«application/vnd.google-apps.script»: [
«application/vnd.google-apps.script+json»
],
«application/vnd.google-apps.presentation»: [
«application/vnd.oasis.opendocument.presentation»,
«application/pdf»,
«application/vnd.openxmlformats-officedocument.presentationml.presentation»,
«text/plain»
]
>
>
У «ресурса» .files (которым мы в основном и будем пользоваться) также есть большое количество методов, рассмотрим основные из них.
С методом files().list() уже немного знакомы, но давайте подробнее.
Метод .list() позволяет находить файлы и папки (используя определённые запросы).
list_example = drive_service.files().list(q='fullText contains "important" and trashed = true', fileds='files(id, name)')
Здесь мы воспользовались таким важным параметром как q — особый вид запроса, позволяющий выбрать из всего потока только нужную нам информацию.
Работает на логическом полуестественном языке, можно рассматривать различные параметры, выглядят запросы примерно так
q = 'name = "Habrahabr"' q = 'fullText contains "some text"' q = '"idexample123" in parents'
Подробнее о том как этим орудовать здесь.
Пункт fileds регулирует какую именно информацию о файлах мы хотим получить (чтобы запросы выполнялись быстрее). Касается это любого запроса.
Можно также посмотреть базовые примеры работы — загрузка файлов и скачивание файлов. Не стал рассматривать их отдельно, потому что дальше будет их применение «в боевых условиях», что более полезно.
Исходная загрузка файлов
Впрочем, хватит теории, перейдем уже к веселой части (ради этого здесь и собрались).
Для того чтобы синхронизировать папку на компьютере с папкой в облаке, сначала нужно чтобы было что синхронизировать и там и там. В принципе, можно загрузить папку вручную через браузер, но в таком случае можно вручную обновлять файлы по отдельности, вообще сюда не приходить. Так что будем загружать папку с помощью пары строчек кода, магии и костылей.
Если вы все же загружаете папку вручную/уже имеете такую на диске и не хотите ничего менять, то просто переходите к следующему пункту (только примечание — в нашем конкретном случае папка создается прямо в корневой директории гугл диска, так что имейте это ввиду, возможно потребуется a little bit of tinkering).
Напишем функцию, которая будет загружать нашу папку на диск
Код функции
def folder_upload(service): parents_id = <> for root, _, files in os.walk(FULL_PATH, topdown=True): last_dir = root.split('/')[-1] pre_last_dir = root.split('/')[-2] if pre_last_dir not in parents_id.keys(): pre_last_dir = [] else: pre_last_dir = parents_id[pre_last_dir] folder_metadata = create_folder = service.files().create(body=folder_metadata, fields='id').execute() folder_id = create_folder.get('id', []) for name in files: file_metadata = media = MediaFileUpload( os.path.join(root, name), mimetype=mimetypes.MimeTypes().guess_type(name)[0]) service.files().create(body=file_metadata, media_body=media, fields='id').execute() parents_id[last_dir] = folder_id return parents_id
Разберем по порядку, хотя здесь все пока довольно просто.
FULL_PATH — глобальная переменная, содержащая полный путь к требуемой папке.
Мы «пробегаем» нашу папку спускаясь «сверху вниз». Для каждой новой папки создаем ее брата близнеца на гугл диске, ее id сохраняем в словарь (ключ — имя, значение — id), а все встречающиеся файлы загружаем в соответствующую папку. В конце возвращаем этот словарь.
Правда, как в анекдоте, есть один нюанс. Для загрузки файла на диск требуется указать его mimeType (спецификация для кодирования информации, не спрашивайте, я не знаю). Для упрощения работы с этим делом воспользуемся готовым решением (по сути оно просто предполагает соответствующий mimeType по расширению, если я правильно понял из документации).
Так что если у Вас есть какие-то хитрые файлы или файлы без расширения, перед применением программы проконсультируйтесь со специалистом (будьте осторожнее).
Синхронизируем изменения с компьютера в облако

Вот загрузили мы папку, поделали каких то изменений, что-то удалили, что-то добавили, что-то просто подредактировали, надо бы теперь сделать так чтобы эти изменения отразились на нашей облачной копии.
Очевидно удалять и загружать заново просто так не очень хочется, поэтому «мы пойдем другим путем».
Создадим для этого отдельный python — скрипт, подгружаем необходимые библиотеки. Для анализа изменений файлов нужно получить дерево файлов и папок на Диске и локальном хранилище, чтобы затем их сравнить и эти изменения перенести туда или обратно.
В достаточно богатом на возможности апи нет встроенного способа получить всё дерево папок и файлов (ну или я не нашел и тогда зря велосипед собрал).
А раз нет, так напишем сами!
Код функции загрузки файлов на Google Диск
def get_tree(folder_name, tree_list, root, parents_id, service): folder_id = parents_id[folder_name] results = service.files().list( pageSize=100, q=("%r in parents and \ mimeType = 'application/vnd.google-apps.folder'and \ trashed != True" % folder_id)).execute() items = results.get('files', []) root += folder_name + os.path.sep for item in items: parents_id[item['name']] = item['id'] tree_list.append(root + item['name']) folder_id = [i['id'] for i in items if i['name'] == item['name']][0] folder_name = item['name'] get_tree(folder_name, tree_list, root, parents_id, service)
Разберем подробнее.
На вход подается куча параметров
folder_name — исходное название нашей папки
folder_id — исходное id папки
tree_list — список наших путей, изначально пустой []
root — промежуточный путь директории… которые потом сохраняются в tree_list
parents_id — словарь, содержащий пары
Делаем исходный запрос на содержимое папки с (и еще те что не в корзине*), выдираем те из них которые папки (потому что сейчас интересуемся только путями).
Сохраняем имена и id этих папок в словарь parents_id, в строке root отмечаем тот факт что спускаемся вниз по иерархии папок, и для каждой новой встреченной папки рекурсивно запускаем get_tree с параметрами уже этой папки.
Таким образом рекурсивно спускаемся по всем папкам и получаем их пути.
//Примечание1: У гугл Диска какая-то особая файловая система (что наверное логично), которая обладает своими законами и правилами. Например рядом в одном каталоге могут лежать две папки или два файла с одинаковыми названиями, потому что уникальными для файлов являются их идентификаторы — id. К тому же один и тот же файл может быть одновременно в двух разных местах на диске (если я все правильно понял). Наверное эти знания можно было использовать для более оптимизированной синхронизации, построить базу данных рядом со скриптом и проверять по ней, но это уже overfitting и совсем лишнее. Просто на заметку.
// Примечание2: все мои примеры, и даже итоговый скрипт сделаны с одним халатным допущением, считается что во папке находится не больше 1000 файлов (и так сойдет!). В моем случае это всегда верно, себе я доверяю. Поэтому так грубо и непредусмотрительно написано. Проблема исправляется легко и в пару строчек с использованием nextPageToken, как показано в пункте выше. Думаю Вам не составит труда это сделать самим (ну или у меня когда-нибудь дойдут руки).
Пример кода с использованием nextPageToken также есть в специальной инструкции.
Отлично, получили папки которые имеются на диске, теперь проделаем то же самое
с папкой на компьютере (это делается уже проще)
os_tree_list = [] root_len = len(full_path.split(os.path.sep)[0:-2]) for root, dirs, files in os.walk(full_path, topdown=True): for name in dirs: var_path = '/'.join(root.split('/')[root_len+1:]) os_tree_list.append(os.path.join(var_path, name))
Здесь по сути только одна хитрость — это превращение полного пути в относительный. Остальное довольно просто.
Теперь у нас имеются tree_list и os_tree_list, которые мы намереваемся сравнить.
Примеры того, как выглядят эти списки
os_tree_list = [Example/Example1, Example/Example1/Example2, Example/Example1/Example3] tree_list = [Example/Example1/, Example/Example1/Example4, Example/Example1/Example4/Example5]
Для дальнейших действий разобьем папки на три группы
remove_folders = list(set(tree_list).difference(set(os_tree_list))) upload_folders = list(set(os_tree_list).difference(set(tree_list))) exact_folders = list(set(os_tree_list).intersection(set(tree_list)))
Как очевидно следует из названия переменных, remove_folders это те папки, которые старые либо окзались здесь случайно и их требуется удалить, upload_folders — новые папки которые нужно загрузить, ну и exact_folders — это папки которые имеются и на компьютере и в облаке.
Начнем с простого — загрузки папок и содержащихся в них папок, благо с этим уже немного знакомы.
Загрузка папок на Диск
upload_folders = sorted(upload_folders, key=by_lines) for folder_dir in upload_folders: var = os.path.join(full_path.split(os.path.sep)[0:-1]) + os.path.sep variable = var + folder_dir last_dir = folder_dir.split(os.path.sep)[-1] pre_last_dir = folder_dir.split(os.path.sep)[-2] files = [f for f in os.listdir(variable) if os.path.isfile(os.path.join(variable, f))] folder_metadata = create_folder = service.files().create( body=folder_metadata, fields='id').execute() folder_id = create_folder.get('id', []) parents_id[last_dir] = folder_id for os_file in files: some_metadata = os_file_mimetype = mimetypes.MimeTypes().guess_type( os.path.join(variable, os_file))[0] media = MediaFileUpload(os.path.join(variable, os_file), mimetype=os_file_mimetype) upload_this = service.files().create(body=some_metadata, media_body=media, fields='id').execute() upload_this = upload_this.get('id', [])
Перед началом действа мы отсортировали наш список с «адресами» папок для удобства по числу поддиректорий (или проще наклонных черточек ‘\’), чтобы загружать папки и их содержимое по мере погружения вглубь иерархического дерева (избегая таким образом возможных опасностей типа «а этой папки нет и непонятно куда она вообще его выкинет»).
Создаем эту папку на диске в соответствующем для нее месте, с указанием ее «родителя» (для этого и нужен pre_last_dir).
По аналогии с папками, смотрим файлы в директории и проверяем их наличие в это же папке на диске.
Берем все файлы из этой папки и по очереди загружаем по известному сценарию.
Дальше чуть интереснее, будем пробегаться по файлам и проверять их на измену изменения.
Теперь предстояло сравнить файлы присутствующие по обе стороны баррикад, и в случае необходимости обновить их содержимое на Диске.
Для этого у файлов есть специальный метод есть .update(), однако не все так просто.
Изначальный вариант предполагал не обновление, а удаление — загрузку новой версии файла (просто с первой попытки метод update() не завёлся, я запаниковал и решил что он слишком хитрый и заменил его на привычный и родной upload()).
Хорошо что решил ещё раз протестировать, и все заработало, стоило только правильно указать mimeType, в очередной раз напоминаю — будьте с ним внимательнее.
Кстати выигрыш по скорости на глаз не был заметен, даже наоборот, но никаких даже приблизительных замеров не производилось, так что это не точно.
Затем стоило разобраться все-таки, имеет ли вообще смысл обновлять файл, иначе если каждый раз все эти файлы загружать (полностью или частично) будет не комильфо.
Первая же пришедшая в голову идея была такая — проверка по дате последней модификации, благо для файла такой параметр вынуть не составляет труда (параметр modifiedTime).
И вроде все ничего, на стандартных проверках все работало как часы. Но пытливые умы уже наверное поняли в чем здесь фатальное упущение. Да, естественно, если мы просто закинем файл из другой папки с таким же названием, но другим содержимым, то дата изменения будет старой, а файл другим совершенно (один из вариантов, видимо таких ситуаций еще много можно придумать). Значит нужно было придумать новый способ проверки (не менее гениальный, но более действенный). В итоге абсолютно самостоятельно, без чьей либо помощи, был придуман вариант проверять не только дату изменения, а хеши файлов (ну кто вообще мог подумать что у файлов на диске есть параметр md5Checksum). В итоге логика изменилась не сильно, а результат радует.
for folder_dir in exact_folders: var = (os.path.sep).join(full_path.split( os.path.sep)[0:-1]) + os.path.sep variable = var + folder_dir last_dir = folder_dir.split(os.path.sep)[-1] # print(last_dir, folder_dir) os_files = [f for f in os.listdir(variable) if os.path.isfile(os.path.join(variable, f))] results = service.files().list( pageSize=1000, q=('%r in parents and \ mimeType!="application/vnd.google-apps.folder" and \ trashed != True' % parents_id[last_dir]), fields="files(id, name, mimeType, \ modifiedTime, md5Checksum)").execute() items = results.get('files', []) refresh_files = [f for f in items if f['name'] in os_files] remove_files = [f for f in items if f['name'] not in os_files] upload_files = [f for f in os_files if f not in [j['name']for j in items]] # Check files that exist both on Drive and on PC for drive_file in refresh_files: file_dir = os.path.join(variable, drive_file['name']) file_time = os.path.getmtime(file_dir) mtime = [f['modifiedTime'] for f in items if f['name'] == drive_file['name']][0] mtime = datetime.datetime.strptime( mtime[:-2], "%Y-%m-%dT%H:%M:%S.%f") drive_time = time.mktime(mtime.timetuple()) # print(drive_file['name']) # if file['mimeType'] in GOOGLE_MIME_TYPES.keys(): # print(file['name'], file['mimeType']) # print() os_file_md5 = hashlib.md5(open(file_dir, 'rb').read()).hexdigest() if 'md5Checksum' in drive_file.keys(): # print(1, file['md5Checksum']) drive_md5 = drive_file['md5Checksum'] # print(2, os_file_md5) else: # print('No hash') drive_md5 = None # print(drive_md5 != os_file_md5) if (file_time > drive_time) or (drive_md5 != os_file_md5): file_id = [f['id'] for f in items if f['name'] == drive_file['name']][0] file_mime = [f['mimeType'] for f in items if f['name'] == drive_file['name']][0] # File's new content. # file_mime = mimetypes.MimeTypes().guess_type(file_dir)[0] file_metadata = # media_body = MediaFileUpload(file_dir, mimetype=filemime) media_body = MediaFileUpload(file_dir, mimetype=file_mime) # print('I am HERE, ', ) service.files().update(fileId=file_id, media_body=media_body, fields='id').execute()
Те файлы, которые отсутствуют в облаке, загружаем, те что там «лишние» (есть только там, но не на компьютере) — удаляем.
Ну и последнее (а также самое простое) — удаление старых папок
for folder_dir in remove_folders: var = (os.path.sep).join(full_path.split(os.path.sep)[0:-1]) + os.path.sep variable = var + folder_dir last_dir = folder_dir.split('/')[-1] folder_id = parents_id[last_dir] service.files().delete(fileId=folder_id).execute()
Здесь все достаточно просто и лаконично.
Всем радость и счастье. Почти.
Примечание: действия загрузка -> обновление -> удаление папок стоит в таком порядке не случайно. Это сделано на всякий случай, чтобы избежать коллизии вроде «папка была» — «папки внутри нет» (или как-то так). Да, это потенциально может добавить лишней и ненужной работы, но зато безопаснее. К тому же, программа писалась в основном под себя, себе я доверяю и скорее всего сильно много чудить и менять папки не буду (хотя могу, но в таком случае скорее просто все снесу и загружу заново, «такой уж я парень»)
Пункт 3 — обратная синхронизация

Теперь займемся синхронизацией Google Диск -> компьютер. Допустим имеется у нас папка на ноутбуке, поработав день на свежем воздухе и отразив все эти изменения на диске, хотим чтобы чудесным образом все так же появилось (или исчезло) на домашнем ПК.
В принципе логика здесь такая же, как в предыдущем пункте, только наоборот (каламбур, но думаю суть поняли).
Образец кода для скачивания файла примерно такой:
file_id = 'idexample' request = drive_service.files().get_media(fileId=file_id) fh = io.BytesIO() downloader = MediaIoBaseDownload(fh, request) done = False while done is False: status, done = downloader.next_chunk() print "Download %d%%." % int(status.progress() * 100)
И здесь появляется главная трудность. Данный способ работает только с так называемыми «бинарными файлами» (технически не совсем так, ведь текстовые файлы — не бинарные, бла бла бла, не придирайтесь). На практике это значит что все будет хорошо с любыми файлами кроме файлов формата Google Docs. К ним нужен особый подход.
Во-первых, для них существуют отдельный немного свой тип запроса:
file_id = 'idexample' request = drive_service.files().export_media(fileId=file_id, mimeType='application/pdf') fh = io.BytesIO() downloader = MediaIoBaseDownload(fh, request) done = False while done is False: status, done = downloader.next_chunk() print "Download %d%%." % int(status.progress() * 100)
Во-вторых, сохранять их нужно с использованием строго определенных типов mimeType. То есть нужно каждому формату Google Docs файла нужно поставить в соответствие четко определенный поддерживаемый формат (здесь могут пригодиться знания полученные из метода about().get(fields=’exportFormats’) чуть выше, нельзя просто так Google Таблицы сохранить в .doc файле).
Основные моменты не будут сильно от отличаться по своей сути от предыдущего пункта, поэтому не буду приодить весь код целиком, можете посмотреть в (репозитории)[].
C самого начала знакомство с гугл доками у меня не заладилось, постоянно возникали проблемы. Нормально и почти без лишних проблем работало только их сохранение в pdf файл, что полноценно устраивать не может (так так редактировать их будет нельзя).
То есть обратной совместимости (пока что) добиться не удалось, жаль. Не знаю как именно (не смотрел), но видимо гугловский софт по синхронизачии работает довольно хитро, поэтому возможно на linux gui решения и нет (да и не нужно оно).
Настолько длинный и тернистый путь был связан с Google Docs, что я решил выделить «наболевшее» в отдельную главу.
Примечание: вместо io.BytesIO() лично я использую FileIO(path_to_file, ‘wb’), иначе ничего просто не работало, на заметку.
Эпопея с Google Docs

Как же решить проблему обратной совместимости?
Спойлер — наверное её не надо решать. Я так полностью не решил.
Ситуация здесь такая — есть все «обычные» файлы, а есть файлы формата Google Docs. И вот на компьютер просто так сохранить эти чудесные Гугл Доки никак нельзя, нужно переводить в соответствующий известный формат (например Microsoft, OpenOffice или pdf в случае документов).
После того когда вся программная часть была списана и работала сносно, большая часть времени ушла на выход из этого неловкого положения.
Вообще, писал то я скрипт изначально под свои нужды, и в моей рабочей папке никаких Гугл Доков быть не должно. Но желание здесь все более универсально оказалось сильнее, и пара ночей была потрачена только на решение проблемы совместимости.
Ход эволюции мысли здесь был примерно такой:
1) Сначала было решено ничего не делать с этими веб файлами, просто при проверке папкой либо их игнорировать, либо скачивать PDF и этого будет достаточно. Но это уж слишком ситуативно, можно лучше.
2) А почему бы не перегонять их в соответствующий Microsoft формат (для презентаций и т.п., благо такой вариант возможно) а потом обратно? Здесь явно нужно было уже работать с обновлением файла, простого удаления — загрузки не хватит (собственно в этот момент я снова решил попробовать метод .update()), ибо вдруг этот файл расшарен, при загрузке у него сменится id и старая ссылка работать не будет. Не то чтобы это мне было нужно, но раз уж взялся за дело, отступать было поздно.
И вот на этом моменте и возникла самая большая куча подводных камней. Итоговый код вот (на самом деле не очень сложный)
#f - список, состоящий из имений файла, его id, и других полехные вещей вроде mimeType и др. if f['mimeType'] in GoogleMimeTypes.keys(): print('File APPLICATION. ', f['name'], f['mimeType']) # request = service.files().get_media(fileId=file_id) request = service.files().export_media(fileId=file_id, mimeType = GoogleMimeTypes[f['mimeType']]) fh = io.FileIO(os.path.join(variable, f['name']), 'wb') downloader = MediaIoBaseDownload(fh, request) done = False while done is False: status, done = downloader.next_chunk() print("Download %d%%." % int(status.progress() * 100), GoogleMimeTypes[f['mimeType']]) else: print('Good File ', f['name'], f['mimeType']) request = service.files().get_media(fileId=file_id) fh = io.FileIO(os.path.join(variable, f['name']), 'wb') downloader = MediaIoBaseDownload(fh, request) done = False while done is False: status, done = downloader.next_chunk() print("Download %d%%." % int(status.progress() * 100))
А вот некоторые проблемы с которым пришлось бороться / мириться (может умные люди выйдут из положения более элегантно)
1) Несмотря на заявленную карту соответствий, не в каждый формат удалось перевести конкретные файлы (например почему-то таблицы лично у меня очень плохо сохраняются в pdf).
2) Проблемы с mimeType и расширениями. У Google Файлов (поскольку это веб формат) расширений нет, соответственно и при сохранении у файла не будет. Но Майкрософт файлы просто так без расширения не работают (без расширения это просто xml архив, который так просто в ворде не запустить), да и другие файлы тоже без расширений могут вести себя непредсказуемо.
3) Вообще молчу про файлы не входящие в офис-пакет. Мало кто знает, но Google Docs также имеет в своем арсенале Drawings, Forms и кучу всего другого, что вообще никак нормально не переводится. Яркий пример — Google Drawings, которые вообще нормально нельзя перевести «туда-обратно-туда» (можно посмотреть это в exportFormats и importFormats). В итоге на эти вещи было решено конкретно забить в надежде что в жизни они никогда и никому не встретятся.
Поэтому был реализован дикий костыль: ко всем Google Docs файлам в название приписывается .ext расширение, соответствующее аналогу в мире Microsoft. И при сохранении (экспорте) в таком случае файл на компьютере будет соответствовать всем ожиданиям и будет нормально работать и запускаться. Соответственно пришлось немного переписать логику работы по синхронизации компьютер -> Диск, этот файл будет обновлять веб-версию Google Doc файла, а не просто стирать ее и заменять на Office документ (соответственно название файла все равно один раз пострадает, что может повлиять на его доступность при расшаривании, возможно).
Поверхностная проверка проблем не выявила.
Пункт про аналоги
Да, стоит наверное уточнить момент связанный с «аналогов не нашел или они все хуже». Положа руку на сердце, это не совсем так. Изначально поиски были под убунту, и на глаза попалась пара интересных примеров (не говоря уже об известной программе grive), но лично меня они не устраивают, где-то синхронизация только в одну сторону, где-то все работает неудобно и неестественно через создание какой-то лишней искусственной папки, где-то еще что-то неудобно. Оправдался в общем за создание очередного велосипеда. Вот так вот.
Заключениe
Пора уже подводить итоги.
Что-то еще осталось «допилить» и что-то не идеально. Но основная цель была достигнута. В планах еще немного это все подшлифовать, возможно добавить таблицы или маленькую БД и хранить там данные о Google Docs файлах, чтобы не менять название, а просто ставить в соответствие файлу на компьютере файл в облаке. Но это сложно,»из пушки по воробьям», вероятно поэтому пока и откладываю. На сегодня меня текущее решение устраивает.
Также в планах дописать немного, чтобы можно было использовать относительные пути, просто положив скрипт рядом с синхронизируемой папкой.
Жду комментариев, критики и советов, как это дело можно элегантно подправить.
Исходники можно посмотреть в репозитории.
Полезные ссылки, еще раз:
Загрузка или обновление файла на гугл диске
Для взаимодействием с api гугл диска необходимо создать проект в Google, дать доступ и получить ключи. Данные действия в своей публикации я описывать не буду, более подробно написано в этой публикации //infostart.ru/public/651450/ или
Программный код
// Функция - Обновление токена // // Параметры: // ClientId - Строка // ClientSecret - Строка // RefreshToken - Строка // // Возвращаемое значение: // Структура. Ключи структуры: access_token,expires_in,access_lifetime,ОписаниеОшибки // Функция ОбновлениеТокена(ClientId, ClientSecret, RefreshToken) СтруктураВозврата = Новый Структура("access_token,expires_in,access_lifetime,ОписаниеОшибки", Неопределено, Неопределено, Неопределено, Неопределено); ПараметрыЗапроса = ""; ПараметрыЗапроса = ПараметрыЗапроса + "client_id=" + ClientId; ПараметрыЗапроса = ПараметрыЗапроса + "&client_secret=" + ClientSecret; ПараметрыЗапроса = ПараметрыЗапроса + "&refresh_token=" + RefreshToken; ПараметрыЗапроса = ПараметрыЗапроса + "&grant_type=refresh_token"; ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено); Соединение = Новый HTTPСоединение("www.googleapis.com", , , , , ,ЗащищенноеСоединение); Заголовки = Новый Соответствие; Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded"); Заголовки.Вставить("Content-Charset", "utf-8"); ОписаниеОшибки = ""; HTTPЗапрос = Новый HTTPЗапрос("/oauth2/v4/token", Заголовки); HTTPЗапрос.УстановитьТелоИзСтроки(ПараметрыЗапроса, КодировкаТекста.UTF8); Результат = Соединение.ОтправитьДляОбработки(HTTPЗапрос); Если Результат.КодСостояния <> 200 И Результат.КодСостояния <> 204 тогда СтрокаОтвет = Результат.ПолучитьТелоКакСтроку(); ВызватьИсключение СтрокаОтвет; КонецЕсли; ТекущаяДата = ТекущаяДата(); СтрокаОтвет = Результат.ПолучитьТелоКакСтроку(); Чтение = Новый ЧтениеJSON; Чтение.УстановитьСтроку(СтрокаОтвет); ДанныеОтвет = ПрочитатьJSON(Чтение, Ложь); Чтение.Закрыть(); Если Не ДанныеОтвет = Неопределено Тогда Если ДанныеОтвет.Свойство("error") Тогда ОписаниеОшибки = СтрШаблон( "error=%1: %2", ДанныеОтвет.error, ДанныеОтвет.error_description ); Иначе СтруктураВозврата.access_token = ДанныеОтвет.access_token; СтруктураВозврата.expires_in = ДанныеОтвет.expires_in; СтруктураВозврата.access_lifetime = ТекущаяДата + Число(ДанныеОтвет.expires_in); КонецЕсли; Иначе СтруктураВозврата.ОписаниеОшибки = НСтр("ru='Не получены данные от сервера!'"); КонецЕсли; Возврат СтруктураВозврата; КонецФункции // Функция - Авторизация // // Параметры: // AuthorizationCode - Строка // ClientId - Строка // ClientSecret - Строка // // Возвращаемое значение: // Структура. Ключи структуры: access_token,expires_in,access_lifetime,refresh_token,ОписаниеОшибки // функция Авторизация(AuthorizationCode, ClientId, ClientSecret) СтруктураВозврата = Новый Структура("access_token,expires_in,access_lifetime,refresh_token,ОписаниеОшибки", Неопределено,Неопределено,Неопределено,Неопределено,Неопределено); ПараметрыЗапроса = ""; ПараметрыЗапроса = ПараметрыЗапроса + "code=" + AuthorizationCode; ПараметрыЗапроса = ПараметрыЗапроса + "&client_id=" + ClientId; ПараметрыЗапроса = ПараметрыЗапроса + "&client_secret=" + ClientSecret; ПараметрыЗапроса = ПараметрыЗапроса + "&redirect_uri=urn:ietf:wg:oauth:2.0:oob"; ПараметрыЗапроса = ПараметрыЗапроса + "&grant_type=authorization_code"; ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено); Соединение = Новый HTTPСоединение("www.googleapis.com", , , , , ,ЗащищенноеСоединение); Заголовки = Новый Соответствие; Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded"); Заголовки.Вставить("Content-Charset", "utf-8"); ОписаниеОшибки = ""; HTTPЗапрос = Новый HTTPЗапрос("/oauth2/v4/token", Заголовки); HTTPЗапрос.УстановитьТелоИзСтроки(ПараметрыЗапроса, КодировкаТекста.UTF8); Результат = Соединение.ОтправитьДляОбработки(HTTPЗапрос); Если Результат.КодСостояния <> 200 И Результат.КодСостояния <> 204 тогда СтрокаОтвет = Результат.ПолучитьТелоКакСтроку(); ВызватьИсключение СтрокаОтвет; КонецЕсли; ТекущаяДата = ТекущаяДата(); СтрокаОтвет = Результат.ПолучитьТелоКакСтроку(); Чтение = Новый ЧтениеJSON; Чтение.УстановитьСтроку(СтрокаОтвет); ДанныеОтвет = ПрочитатьJSON(Чтение, Истина); Чтение.Закрыть(); Если Не ДанныеОтвет = Неопределено Тогда Если НЕ ДанныеОтвет.Получить("error") = Неопределено Тогда ОписаниеОшибки = СтрШаблон( "error=%1: %2", ДанныеОтвет.Получить("error"), ДанныеОтвет.Получить("error_description") ); Иначе СтруктураВозврата.access_token = ДанныеОтвет.Получить("access_token"); СтруктураВозврата.expires_in = ДанныеОтвет.Получить("expires_in"); СтруктураВозврата.access_lifetime = ТекущаяДата + Число(СтруктураВозврата.expires_in); СтруктураВозврата.refresh_token = ДанныеОтвет.Получить("refresh_token"); КонецЕсли; Иначе СтруктураВозврата.ОписаниеОшибки = НСтр("ru='Не получены данные от сервера!'"); КонецЕсли; Возврат СтруктураВозврата; КонецФункции // Процедура - Обновить существующий файл на гугл диске // // Параметры: // ПутьКФайлу - путь к файлу (данные файла, который необходимо обновить // fileId - id файла на гугл диске, который необходимо обновить // access_token - токен // mimeType - "XLSX", "application/vnd.ms-excel // "XLS", "application/vnd.ms-excel" // "XLS95", "application/vnd.ms-excel" // "XLS97", "application/vnd.ms-excel" // "DOCX", "application/msword" // "HTML", "text/html" // "HTML3", "text/html" // "HTML4", "text/html" // "HTML5", "text/html" // "ODS", "application/vnd.oasis.opendocument.spreadsheet" // "PDF", "application/pdf" //Другие типы можно посмотреть в документации к апи // Процедура ОбновитьСуществующийФайлНаГуглДиске(ПутьКФайлу, access_token, mimeType, fileId) Экспорт Файл = Новый Файл(ПутьКФайлу); boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", ""); //Метаданные файла > //Данные файла > //Формирование тела запроса > Заголовки = Новый Соответствие; Заголовки.Вставить("Authorization", "Bearer " + access_token); Заголовки.Вставить("Content-Type", "Multipart/Related; boundary=" + boundary); Заголовки.Вставить("Content-Length", Формат(ДвоичныеДанныеТело.Размер(), "ЧГ=")); HTTPЗапрос = Новый HTTPЗапрос("/upload/drive/v3/files/" + fileId + "?uploadType=multipart", Заголовки); HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТело); SSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено); Соединение = Новый HTTPСоединение("www.googleapis.com". SSL); Результат = Соединение.Изменить(HTTPЗапрос);//patch запрос Если Результат.КодСостояния <> 200 И Результат.КодСостояния <> 204 тогда СтрокаОтвет = Результат.ПолучитьТелоКакСтроку(); ВызватьИсключение СтрокаОтвет; КонецЕсли; КонецПроцедуры // Процедура - Обновить существующий файл на гугл диске // // Параметры: // ПутьКФайлу - путь к файлу (данные файла, который необходимо обновить // fileId - id файла на гугл диске, который необходимо обновить // access_token - токен // mimeType - "XLSX", "application/vnd.ms-excel // "XLS", "application/vnd.ms-excel" // "XLS95", "application/vnd.ms-excel" // "XLS97", "application/vnd.ms-excel" // "DOCX", "application/msword" // "HTML", "text/html" // "HTML3", "text/html" // "HTML4", "text/html" // "HTML5", "text/html" // "ODS", "application/vnd.oasis.opendocument.spreadsheet" // "PDF", "application/pdf" //Другие типы можно посмотреть в документации к апи // Процедура ЗагрузитьФайлНаГуглДиск(ПутьКФайлу, access_token, mimeType) Экспорт Файл = Новый Файл(ПутьКФайлу); boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", ""); //Метаданные файла > //Данные файла > //формирование тела запроса > Заголовки = Новый Соответствие; Заголовки.Вставить("Authorization", "Bearer " + access_token); Заголовки.Вставить("Content-Type", "Multipart/Related; boundary=" + boundary); Заголовки.Вставить("Content-Length", Формат(ДвоичныеДанныеТело.Размер(), "ЧГ=")); HTTPЗапрос = Новый HTTPЗапрос("/upload/drive/v3/files?uploadType=multipart", Заголовки); HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТело); SSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено); Соединение = Новый HTTPСоединение("www.googleapis.com". SSL); Результат = Соединение.ОтправитьДляОбработки(HTTPЗапрос);// post запрос Если Результат.КодСостояния <> 200 И Результат.КодСостояния <> 204 тогда СтрокаОтвет = Результат.ПолучитьТелоКакСтроку(); ВызватьИсключение СтрокаОтвет; КонецЕсли; КонецПроцедуры
В процедурах загрузки и обновления файлов передан не полный набор параметров (в данном коде передаются только те параметры, которые были необходимы мне при загрузке/обновлении файлов на гугл диске). При необходимости можно указать папку, в которую необходимо поместить файл, произвольное наименование файла, описание и т.д. Официальная документация по созданию файла —
См. также
[ED3] Обмен для ERP 2.5, КА 2.5, УТ 11.5 БП 3.0, Розница, УНФ и других с EnterpriseData (универсальный формат обмена), правила обмена
Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб) Правила в универсальном формате обмена для ERP 2.5, КА 2.5, УТ 11.5, БП 3.0, Розница, УНФ, для последних версий конфигураций. Ссылки на другие конфигурации в описании публикации. Правила совместимы со всеми другими версиями конфигураций новыми и старыми, поддерживающими обмен в формате EnterpriseData. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой. 22320 руб. 12.06.2017 131234 686 290 378
378 686 290 131234
Перенос данных из УПП 1.3 в БП 3.0. Переносятся документы (обороты за период), справочная информация и остатки
Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб) Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С: Бухгалтерия предприятия 3.0 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. Правила тестировались на конфигурациях УПП 1.3 (1.3.212.x) и БП 3.0 (3.0.142.x). Правила подходят для версии ПРОФ и КОРП. 25000 руб. 15.12.2021 17926 109 36 65
65 109 36 17926
Перенос данных из УТ 10.3 в УТ 11.5. Переносятся документы (обороты за период), справочная информация и остатки
Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 10 1С:Управление торговлей 11 Россия Управленческий учет Платные (руб) Перенос данных из 1С:Управление торговлей 10.3 в 1С:Управление торговлей 11.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. За основу были взяты стандартные правила переноса остатков и справочной информации. Правила тестировались на конфигурациях УТ 10.3 (10.3.85.x) и УТ 11.5 (11.5.14.x). 25000 руб. 23.07.2020 42888 183 63 135
135 183 63 42888
Загрузка номенклатуры c картинками (несколько потоков одновременно) и сопутствующими данными в базу и любые документы из yml, xls, xlsx, xlsm, ods, ots, csv для УТ 10.3, УТ 11 (все), БП 3, КА 2, ERP 2, УНФ 1.6/3.0, Розница 2
Загрузка и выгрузка в Excel Логистика, склад и ТМЦ Ценообразование, анализ цен Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб) Эволюция не стоит на месте — новая удобная версия функциональной обработки для Вашего бизнеса! Что же Вы получаете? Удобный и интуитивно понятный интерфейс с 3-мя этапами работы. 2 режима — автоматический и ручной. Чтение XLSX, XLSM, CSV, XML/YML форматов без офиса, на любом сервере! Визуальное связывание колонок файла и реквизитов простым перетаскиванием колонок. Создание или обновление номенклатуры с иерархией, характеристик, доп. реквизитов, упаковок, загрузка практически неограниченного количества картинок на одну номенклатуру (с возможностью загрузки в несколько потоков одновременно), с хранением в томах или в базе. Загрузка номенклатуры поставщиков или поиск по их данным номенклатуры. Загрузка доп. реквизитов в характеристики. Загрузка штрихкодов с генерацией новых. Создание элементов справочников и ПВХ «на лету» для выбранных реквизитов. (Обновление от 14.05.2023, версия 9.4 — 9.8) 6000 руб. 20.11.2015 146947 342 371 479
479 342 371 146947
[ED2] Обмен УПП 1.3, КА 1.1, УТ 10.3 с EnterpriseData (универсальный формат обмена), обработка
Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 Платформа 1C v8.2 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Управление производственным предприятием Россия Платные (руб) Регулярный обмен, выгрузка, перенос из КА 1.1, УПП 1.3, УТ 10.3 для обмена с любыми конфигурациями, поддерживающими обмен в формате EnterpriseData (КД3) — БП 3.0, ERP, КА 2, УТ 11, Розница 2, УНФ 1.6 и другими. Правила для старых и доработанных конфигураций не требуют синхронного обновления и совместимы с новыми и будущими конфигурациями. Обмен по расписанию, через папку, FTP, почту. 12960 руб. 18.02.2016 179410 545 508 497
497 545 508 179410
Выгрузка-загрузка любых данных (и измененных) между похожими конфигурациями (ФАЙЛ, HTTP, COM) ЛЮБЫХ баз 1С 8.1-8.3 с обработкой и поиском данных по произвольным полям поиска
Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб) Что же Вы получаете? 2 способа обмена объектами – с ОДИНАКОВОЙ структурой и с ОТЛИЧАЮЩЕЙСЯ! Забудьте о том, что не могли ранее перенести данные между базами, из-за того, что изменилась структура объектов в одной из них с обновлением конфигурации – теперь это в прошлом! Теперь не помеха для обмена изменение состава реквизитов объекта (измерений, ресурсов)/состава табличных частей/реквизитов табличных частей/типов реквизитов! А так же получаете быстрый алгоритм обмена, с возможностью указания уровня выгрузки объектов по ссылкам! 3 способа обмена — ФАЙЛ, HTTP, COM: Система слежения за дублями предопределенных элементов при загрузке; Система поиска связей объектов для выгрузки; Отборы для каждого объекта конфигурации в отдельности; Динамическая замена произвольных ссылок при обмене; Выбор регистров движений для выгрузки. (Обновление от 22.07.2023, версия 8.10 — 10.0) 12000 руб. 28.08.2012 199734 276 277 622
622 276 277 199734
Перенос данных из УПП 1.3 в ERP 2.5, КА 2.5. Переносятся документы (обороты за период), справочная информация и остатки
Обмен между базами 1C Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 Бухгалтерский учет Управленческий учет Платные (руб) Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:ERP Управление предприятием 2.5 и 1С:Комплексную автоматизацию 2.5 с помощью правил обмена. Переносятся остатки, документы (обороты за период), справочная информация. За основу были взяты стандартные правила переноса остатков и справочной информации. Правила тестировались на конфигурациях УПП 1.3 (1.3.214.x), ERP 2.5 (2.5.14.x), КА 2.5 (2.5.14.x) . 25000 руб. 24.06.2020 59072 34 27 64
64 34 27 59072
Управление доставками Boxberry, СДЭК, ЭкстраПочта, Почта России, Энергия, DPD, ПЭК, Grastin, Деловые Линии, КСЕ, Dalli
54 228 93 52470
Посмотреть ещё
Комментарии
- Дата
- Дата
- Рейтинг всех уровней
- Рейтинг 1-го уровня
- Древо развёрнутое
- Древо свернутое
Свернуть все
1. aatm 12.10.20 10:35 Сейчас в теме
Мне очень помогла эта статья громадное спасибо! Всё просто и доступно, заработало с первого раза. Автор молодец!
pavelpribytkin96; + 1 – Ответить
2. flegma2013 14.10.20 19:06 Сейчас в теме
Автор, подскажите как получить RefreshToken, имея только client_id и client_secret», не сильно сильна в веб программирование, сижу уже весь день.. ничего не взлетает(((
3. flegma2013 14.10.20 23:41 Сейчас в теме
разобралась, осталось только понять как выгружать файлы в определенную папку, заданную
4. pavelpribytkin96 569 17.10.20 15:58 Сейчас в теме
(3)Смотрите документацию по методу https://developers.google.com/drive/api/v3/reference/files/create .
На сколько я помню необходимо в запрос передать параметр «parents».
5. flegma2013 19.10.20 08:14 Сейчас в теме
да, я побывала но ничего не выходит, я передавала имя папки, а там скорее всего id нужно, только как его получить от гугл .вот вопрос((..
6. pavelpribytkin96 569 20.10.20 02:45 Сейчас в теме
(5)да, необходимо передать массив id папок. Читайте документацию, на сколько я помню через метод list можно получить список id файлов и папок на диске. Нужного примера кода нет под рукой.
7. andy23 464 16.10.21 13:52 Сейчас в теме
Добрый день!
А не подскажите как при обновлении фала, определить (найти) fileId уже залитого на гугл драйв?
8. Trof@ 27.07.22 23:37 Сейчас в теме
Что-то не выходит никак. Как я понимаю сначала нужно выполнить Функцию Авторизация. У меня есть ClientId и ClientSecret, а где взять AuthorizationCode ?
user1801638; + 1 – Ответить
9. Darkdimon 07.09.22 15:15 Сейчас в теме
(8) Через браузер можно получить, пример запроса https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=Ваш_client_id &redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/drive
Ваш_client_id не забудьте поменять, Google попросит дать разрешение вашему приложению.
Colaboratory. Работаем с локальной файловой системой Вашего компьютера и Google диском


# wget — закачка с сети Internet на Google диск в папку /content/gdrive/My\ Drive ( My\ Drive — пробел в имени файла в системе Linux экранируется обратным слэшем ) файла с входными данными нейронной сети (в нашем случае: dogscats.zip — множество портретов кошек и собак для обучения и тестирования нейронной сети):
! wget -P /content/gdrive/My\ Drive http://files.fast.ai/data/dogscats.zip
!unzip /content/gdrive/My\ Drive/dogscats.zip -d /content/gdrive/My\ Drive/
!git clone https://github.com/fastai/fastai.git /content/gdrive/My\ Drive/fastai
PATH = «/content/gdrive/My Drive/dogscats/»
os.listdir(PATH)
