Objetivo y Alcance
Existen varias maneras de cargar documentos en una biblioteca de documentos de SharePoint. Algunas son procesos manuales como el que ofrece la propia herramienta o a través del "Guardar como" si estamos hablando de documentos Office. También existen procesos automáticos para este propósito. Uno de ellos son los servicios web.
Sólo debe considerarse como una aproximación ya que no se establecen mecanismos para controlar los errores que se puedan producir por denegación de permisos, tamaño del archivo, carga de archivos ejecutables, etc.
Trabajaremos entonces con el servicio web copy.asmx (operación CopyIntoItems), aunque será fácilmente extensible a los servicios Imaging.asmx (operación Upload) y Lists.asmx (operación AddAttachment). Mientras que el primero nos permite cargar documentos en una biblioteca de documentos el segundo nos permite cargar imágenes en una biblioteca de imágenes y el tercero añadir un adjunto a un elemento de una lista.
Herramienta
Utilizaremos en este caso Visual Basic Script Edition por la facilidad que tiene de ejecución en cualquier estación de trabajo o servidor.
Preliminares
Para conocer las operaciones disponibles del servicio copy.asmx deberemos ejecutar en nuestra instalación de SharePoint la URL: http://<<Misitio>>/_vti_bin/copy.asmx y si queremos conocer la sintaxis de la operación CopyIntoItems : http:// <<Misitio>> /_vti_bin /copy.asmx?op=CopyIntoItems.
Es aquí donde nos damos cuenta que el archivo que carguemos necesita ir codificado en base64Binary. Crearemos objetos que nos permitirán realizar las cuatro funciones principales de las que consta esta aproximación:
Definición de constantes y objetos
Utilizaremos dos constantes: Ruta y nombre del archivo local, URL de la biblioteca de SharePoint incluyendo nombre de archivo destino.
Utilizaremos además cuatro objetos: Un objeto Stream para la lectura del archivo, un elemento de un objeto XMLDOM para la codificación del documento y para la recuperación de la respuesta del servidor y un objeto XMLHTTP para la ejecutar las peticiones.
Const ArchivoLocal = " Ejemplo.pptx " Const URLDestino = " http://.../Biblioteca/Ejemplo.pptx "
Set ObjetoStream = CreateObject(" ADODB.Stream ") Set ObjetoDOM = CreateObject(" Microsoft.XMLDOM ") Set ObjetoElemento = ObjetoDOM.CreateElement(" TMP ") Set ObjetoHTTP = CreateObject(" Microsoft.XMLHTTP ")
Lectura del contenido del archivo y Codificación
A continuación obtenemos el archivo codificado en base64Binary
'Lectura del archivo en binario ObjetoStream.Open ObjetoStream.type= 1 'Tipo Binario ObjetoStream.LoadFromFile(ArchivoLocal) ArchivoBinario = ObjetoStream.Read() ObjetoStream.Close
'Conversion a Base64 ObjetoElemento.DataType = " bin.base64 " 'Tipo Base64 ObjetoElemento.NodeTypedValue = ArchivoBinario ArchivoCodificado = ObjetoElemento.Text
Construcción y ejecución de la Petición de carga del documento
Tal y como se ve en la Imagen 2, la operación SOAP CopyIntoItems se basa en un archivo XML que debemos construir con las constantes definidas y las variables que hemos obtenido. Analizaremos algunos elementos:
'Construye texto Peticion de carga del documento URLServicio = " http://.../_vti_bin/copy.asmx " AccionSOAP = " http://schemas.microsoft.com/sharepoint/soap/CopyIntoItems " Peticion= "<?xml version='1.0' encoding='utf-8'?>"+_ "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"+_ "<soap:Body>"+_ "<CopyIntoItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>"+_ "<SourceUrl>C:/</SourceUrl>"+_ "<DestinationUrls>"+_ "<string>"+URLDestino+"</string>"+_ "</DestinationUrls>"+_ "<Fields>"+_ "<FieldInformation Type='Text' InternalName='Title' DisplayName='Titulo' Value='Archivo cargado con SOAP' />"+_ "</Fields>"+_ "<Stream>"+ArchivoCodificado+"</Stream>"+_ "</CopyIntoItems>"+_ "</soap:Body> </soap:Envelope>"
EjecutaPeticion
Una vez construida la petición podemos enviarla al servidor por medio del procedimiento que utiliza el objeto "Microsoft.XMLHTTP"
Private Sub EjecutaPeticion ObjetoHTTP.Open "Get", URLServicio, false ObjetoHTTP.SetRequestHeader "Content-Type", "text/xml; charset=utf-8" ObjetoHTTP.SetRequestHeader "SOAPAction", AccionSOAP ObjetoHTTP.Send Peticion End Sub
El archivo se carga correctamente en la biblioteca de SharePoint, pero como comentamos antes, el documento almacena un enlace al archivo original. Se trata del parámetro <SourceURL> que se copia en el metadato _CopySource del documento.
Construcción y ejecución de las peticiones adicionales
Podemos desvincular manualmente este documento ya que su origen es un archivo local y no se aplica a nuestro ejemplo. Pero podemos hacerlo programáticamente mediante dos nuevas peticiones, la primera recuperará el ID del elemento publicado y el GUID de la biblioteca y la segunda modificará el metadato _CopySource para que desaparezca el vínculo innecesario.
En la primera petición utilizaremos el servicio web http://<<Misitio>>/_vti_bin/sitedata.asmx con la operación GetURLSegments que incluye en el pedido la URL del documento y nos devuelve el GUID de la Lista y el ID del elemento.
'Peticion para recuperar los Ids del documento cargado URLServicio = "http://.../_vti_bin/sitedata.asmx" AccionSOAP = "http://schemas.microsoft.com/sharepoint/soap/GetURLSegments" Peticion = "<?xml version='1.0' encoding='utf-8'?>"+_ "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"+_ "<soap:Body>"+_ "<GetURLSegments xmlns='http://schemas.microsoft.com/sharepoint/soap/'>"+_ "<strURL>" + URLDestino + "</strURL>"+_ "</GetURLSegments>"+_ "</soap:Body>"+_ "</soap:Envelope>"
EjecutaPeticion
ObjetoDOM.loadXML(ObjetoHTTP.responseText) Set nodeBook = ObjetoDOM.selectSingleNode("//strItemID") IDDocumento = nodeBook.text Set nodeBook = ObjetoDOM.selectSingleNode("//strListID") IDBiblioteca = nodeBook.text
En la segunda petición actualizaremos el metadato _CopySource de este documento actualizándolo a Null. Con esto lograremos eliminar el vínculo al elemento origen que no es necesario en este caso. Utilizaremos el servicio web http://<<Misitio>>/_vti_bin/lists.asmx con la operación UpdateListItems que necesita como parámetros de entrada los dos datos que hemos conseguido con la petición anterior.
'Peticion para actualizar _CopySource en el documento URLServicio = "http://.../_vti_bin/lists.asmx" AccionSOAP = "http://schemas.microsoft.com/sharepoint/soap/UpdateListItems" Peticion = "<?xml version='1.0' encoding='utf-8'?>"+_ "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"+_ "<soap:Body>"+_ "<UpdateListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>"+_ "<listName>" + IDBiblioteca + "</listName>"+_ "<updates>"+_ "<Batch OnError='Return'><Method ID='1' Cmd='Update'><Field Name='ID'>" + IDDocumento + "</Field><Field Name='MetaInfo' Property='_CopySource'></Field></Method></Batch>"+_ "</updates>"+_ "</UpdateListItems>"+_ "</soap:Body>"+_ "</soap:Envelope>"
EjecutaPeticion
WScript.Echo "Documento publicado"
Conclusiones
En este artículo hemos visto cómo utilizar uno de los servicios expuestos por la plataforma SharePoint, copy.asmx, junto con las operaciones disponibles para facilitar el trabajo remoto con información almacenada en un sitio de SharePoint.
Referencias
[1] http://msdn.microsoft.com/en-us/library/ee705814(v=office.14).aspx
[2] http://msdn.microsoft.com/en-us/library/dd955870.aspx
Miguel Ángel García Rodríguez Analista SharePoint miganggarrod@hotmail.com