Office365-rest-python-client: ¿Cómo puedo descargar la carpeta de SharePoint que contiene varios archivos?

Creado en 27 mar. 2019  ·  15Comentarios  ·  Fuente: vgrem/Office365-REST-Python-Client

Mi código de Python 3:

desde office365.runtime.auth.authentication_context import AuthenticationContext
desde office365.sharepoint.client_context import ClientContext

url = ' https://company.sharepoint.com/sites/abc '
ctx_auth = AuthenticationContext (url = url)
si ctx_auth.acquire_token_for_user (username='[email protected] ', contraseña =' 12345 '):
ctx = ClientContext (url, ctx_auth)
listas = ctx.web.lists
ctx.load (listas)
ctx.execute_query ()
para l en listas:
print (l.properties ['Título'])

A partir del código anterior, puedo enumerar los elementos del sitio. Pero mi plan es ejecutar este módulo completo en AWS Lambda usando Python y descargarlo de los documentos de SharePoint y almacenarlo en AWS S3.

Una carpeta puede tener varios archivos. Quiero descargar la carpeta completa con todos los archivos. ¿Alguien hizo esto? ¿Alguna ayuda? ¡Un código que funcione será de gran ayuda ya que soy totalmente nuevo en web scraping!

Comentario más útil

No me agradezcas, @vgrem tiene la culpa :) ... y no estoy seguro, tal vez haya otras formas de lograr lo mismo ...

derecha, para enumerar todas las carpetas dentro de la biblioteca de documentos de documentos compartidos, puede intentar:

    list_object = ctx.web.lists.get_by_title(listTitle)
    folder = list_object.root_folder        
    ctx.load(folder)
    ctx.execute_query()

    folders = folder.folders
    ctx.load(folders)
    ctx.execute_query()

    for myfolder in folders:
        print("File name: {0}".format(myfolder.properties["Name"]))

metro.

Todos 15 comentarios

Hola,
tal vez podrías hacerlo en un bucle, por ejemplo:

  1. devolver el contenido de la biblioteca de documentos de sharepoint primero usando una función:

listTitle = "Documentos"
sitio = "abc"

def fncPrintLibraryContents (ctx, listTitle):

try:

    list_object = ctx.web.lists.get_by_title(listTitle)
    folder = list_object.root_folder        
    ctx.load(folder)
    ctx.execute_query()

    files = folder.files
    ctx.load(files)
    ctx.execute_query()

    return files

except:

    print('Problem printing out library contents')   
    sys.exit(1)
  1. luego descargue cada archivo llamando a un proceso, por ejemplo:

def downloadFile (ctx, fileName):

try:
    with open(fileName, "wb") as localFile:            
        relativeUrl = '/sites/{0}/Shared%20Documents/{1}'.format(site, fileName)
        response = File.open_binary(ctx, relativeUrl)
        localFile.write(response.content) 
        localFile.close()

except:

    print('Problem downloading file:', fileName)
    sys.exit(1)

myfiles = fncPrintLibraryContents (ctx, listTitle)

para myfile en myfiles:
print ("Descargando archivo: {0}". formato (myfile.properties ["Nombre"]))
downloadFile (ctx, `myfile.properties [" Nombre "])

metro.

Por favor, sangra las últimas dos líneas en el bucle for, parece que no puedo hacerlo.
metro.

Oye,

Gracias por una respuesta tan rápida. Puedo descargar con éxito los archivos, dado que tengo que dar hasta el nombre del archivo. Pero, para poder descargar de forma recursiva todos los archivos, primero necesito enumerar todos los existentes en una carpeta en particular que, después de varias pruebas, obtiene errores No encontrados. Tal vez me esté equivocando en alguna parte, porque mi concepto de Título no es correcto, así que cada vez que intento listar una subcarpeta dando ese nombre como título, fallo. Revisaré tu código y veré si puedo hacerlo.

Mientras tanto, mi código de ejecución actual (la descarga funciona bien, la lista de carpetas y archivos para la raíz funciona, pero cada vez que en el Título doy un nombre de carpeta específico que no sea Documentos, falla):

`de office365.runtime.auth.authentication_context importar AuthenticationContext
desde office365.sharepoint.client_context import ClientContext
desde el archivo de importación office365.sharepoint.file
desde office365.sharepoint.file_creation_information importar FileCreationInformation

def read_folder_and_files (contexto, list_title):
"" "Leer un ejemplo de carpeta" ""
list_obj = context.web.lists.get_by_title (list_title)
carpeta = list_obj.root_folder
context.load (carpeta)
context.execute_query ()
print ("URL de lista: {0}". formato (folder.properties ["ServerRelativeUrl"]))

files = folder.files
context.load(files)
context.execute_query()
for cur_file in files:
    print("File name: {0}".format(cur_file.properties["Name"]))

folders = context.web.folders
context.load(folders)
context.execute_query()
for folder in folders:
    print("Folder name: {0}".format(folder.properties["Name"]))

def archivo_descarga (contexto):
respuesta = File.open_binary (contexto, "/ sitios / nuevo / Documentos compartidos / 2011-A / file1.csv")
imprimir (respuesta)
imprimir (respuesta.contenido)
con open (r "C: UsersaakashbDownloadstestfile1.csv", "wb") como archivo_local:
local_file.write (respuesta.contenido)

ctx = Ninguno
url = ' https://company.sharepoint.com/sites/new '
ctx_auth = AuthenticationContext (url = url)
si ctx_auth.acquire_token_for_user (username='[email protected] ', password =' ​​12345 '):
ctx = ClientContext (url, ctx_auth)
read_folder_and_files (ctx, 'Documentos')

print ('función de entrada')

archivo_descarga (ctx)

print ('función de salida') `

1) Perdón por la estructura rota de mi código que te di.
2) Simplemente ejecuté su código y verifiqué, está haciendo exactamente lo que mi código está haciendo en términos de listado. Está enumerando los archivos en la raíz (no dentro de ninguna carpeta). Pero quiero hacer lo mismo con las carpetas.
3) También quiero enumerar las carpetas. Cuando uso el código de @vgrem para enumerar carpetas, no me muestra las carpetas de los Documentos, sino que muestra carpetas como:

Nombre de carpeta: SitePages
Nombre de carpeta: Biblioteca de estilos
Nombre de carpeta: _catalogs
Nombre de la carpeta: FormServerTemplates
Nombre de carpeta: _private
Nombre de la carpeta: compartir enlaces
Nombre de carpeta: SiteAssets
Nombre de la carpeta: imágenes
Nombre de carpeta: Documentos compartidos
Nombre de carpeta: listas
Nombre de carpeta: _cts

Que no es ninguna de las carpetas que tengo en SharePoint Doc Lib.

Entonces, en resumen, ¿cómo puedo enumerar las carpetas Doc Lib y sus respectivos archivos para descargar?

Hola,
mire el problema aquí: https://github.com/vgrem/Office365-REST-Python-Client/issues/91
específicamente en la línea que dice así:

folder = ctx.web.get_folder_by_server_relative_url (app_settings ['urlrel'])

Si no ayuda, me pondré en contacto con usted para brindarle más detalles.
metro.

... lo que quise decir fue usar el método get_folder_by_server_relative_url en lugar de get_by_title, por ejemplo

app_settings = {'urlrel': '/ sites / abc / Shared Documents / TEST'}

def printFolderContents (ctx, listTitle):

try:

    #list_object = ctx.web.lists.get_by_title(listTitle)
    folder = ctx.web.get_folder_by_server_relative_url(app_settings['urlrel'])
    #folder = list_object.root_folder        
    ctx.load(folder)
    ctx.execute_query()
    #print(folder.url)

    files = folder.files
    ctx.load(files)
    ctx.execute_query()

    for myfile in files:
        print("File name: {0}".format(myfile.properties["Name"]))

except:

    print('Problem printing out library contents')   
    sys.exit(1)

Avísame si eso ayuda ...

para descargar los archivos dentro de la carpeta TEST dentro de la biblioteca de Documentos Compartidos, puede, por ejemplo, modificar el código anterior para convertirlo en una función, como:

def fncGetFolderContents (ctx, listTitle):

try:

    #list_object = ctx.web.lists.get_by_title(listTitle)
    folder = ctx.web.get_folder_by_server_relative_url(app_settings['urlrel'])
    #folder = list_object.root_folder        
    ctx.load(folder)
    ctx.execute_query()
    #print(folder.url)

    files = folder.files
    ctx.load(files)
    ctx.execute_query()

    #for myfile in files:
    #    print("File name: {0}".format(myfile.properties["Name"]))

    return files

except:

    print('Problem printing out library contents')   
    sys.exit(1)

y altere un poco la función de descarga, por ejemplo:

def downloadFolderFile (ctx, fileName):

try:
    with open(fileName, "wb") as localFile:            
        relativeUrl = '/sites/{0}/Shared%20Documents/{1}/{2}'.format(site, yourFolder, fileName)
        #relativeUrl = app_settings['urlrel']
        response = File.open_binary(ctx, relativeUrl)
        localFile.write(response.content) 
        localFile.close()

except:

    print('Problem downloading file:', fileName)
    sys.exit(1)

myfiles = fncGetFolderContents (ctx, listTitle)

para myfile en myfiles:
print ("Descargando archivo: {0}". formato (myfile.properties ["Nombre"]))
downloadFolderFile (ctx, myfile.properties ["Nombre"])

¡Muchas gracias hombre! Ustedes dos son muy rápidos en las respuestas, ¡y la API es absolutamente increíble!

Lo revisaré lo antes posible e intentaré replicarlo. Pero, ¿hay alguna forma de listar las carpetas? Quiero decir, el último código que dio funcionará cuando sepa el nombre de la carpeta. En caso de que automatice el proceso y se cree una nueva carpeta y se guarden los archivos, no funcionará para la nueva carpeta, ¿verdad? Es por eso que también quería listar la carpeta, por si acaso. De todos modos, la presente solución debería funcionar para mi caso de uso.

Muchas gracias a los dos. Actualizaré aquí, una vez que ejecute el experimento.

No me agradezcas, @vgrem tiene la culpa :) ... y no estoy seguro, tal vez haya otras formas de lograr lo mismo ...

derecha, para enumerar todas las carpetas dentro de la biblioteca de documentos de documentos compartidos, puede intentar:

    list_object = ctx.web.lists.get_by_title(listTitle)
    folder = list_object.root_folder        
    ctx.load(folder)
    ctx.execute_query()

    folders = folder.folders
    ctx.load(folders)
    ctx.execute_query()

    for myfolder in folders:
        print("File name: {0}".format(myfolder.properties["Name"]))

metro.

Fantástico. ¡La impresión y descarga iterativa del contenido de la carpeta funcionó!

Gracias,

Este código descarga archivos PDF corruptos. Están vacíos: 156 bytes. ¿Alguna idea de por qué?

También obtengo archivos pdf dañados con solo un nombre de archivo de 1 kb al usar el cosde anterior. ¿Alguna idea?

También obtengo archivos pdf corruptos con solo 1 kb de nombre de archivo usando el código anterior. ¿Alguna idea?

Lo descubrí, para mí la razón era la URL relativa. Cuando necesito enumerar el contenido de la carpeta, no necesito agregar / sites / sitename / library, etc., solo tiene que ser / library. Pero cuando ya estoy descargando los archivos, necesito agregar / sites / sitename / folder / file.

Esto es realmente extraño, porque todavía puedo acceder y descargar archivos sin agregar / sites / sitename /, pero el contenido está dañado en ese momento. Al mismo tiempo, si agrego / sites / sitename / cuando obtengo el contenido de la carpeta, arroja un error y solo funciona si comienzo una URL relativa con una biblioteca.

Es extraño que cada recurso sugiera agregar / sites / sitename a la URL relativa tanto para el contenido de la carpeta como para el contenido del archivo.

Gracias por la sugerencia. ¿Puedes compartir el código de trabajo final? Si queremos descargar todo el contenido de una subcarpeta como / sites / sitename / Documents / somefolder, ¿cuál sería el código final?

Gracias chicos. Esto ayuda a resolver muchos problemas y problemas que surgen al usar el paquete Sharepoint.

¿Fue útil esta página
0 / 5 - 0 calificaciones