El otro día recibí una consulta via Twitter sobre como poder subir ficheros a una biblioteca SharePoint. Yo le comente que había escrito varios post al respecto, la persona que me realizó la consulta me dijo se puede hacer con el modelo de objetos cliente de JavaScript? la respuesta es sí pero…. bueno todas las ventajas e inconvenientes de utilizar una opción u otra son las que voy a tratar de explicar en este post, es decir las distintas formas de subir un documento a una biblioteca de SharePoint mediante programación.
Dado que SharePoint es una herramienta que dispone de muchas API’s esta acción de subir un documento a una biblioteca se puede hacer de varias formas: utilizando el modelo de objetos en Cliente de JavaScript o .NET, utilizando la API REST, utilizando el modelo de objetos de Servidor, bien implementando un servicio (Web API/ Manejador).
Utilizando el modelo de objetos JavaScript
En la actualidad gran partes de nuestros desarrollos se centran en utilizar JavaScript, esto nos proporciona una capa frontal mucho más rápida que con los tradicional WebParts (el maestro Gustavo dice que en 4 años ya no desarrollaremos ningún WebPart). Para subir el fichero lo podemos hacer de la siguiente forma:
var ctx = new SP.ClientContext.get_current(); var createInfo = new SP.FileCreationInformation(); createInfo.set_content(content); //setting the content of the new file createInfo.set_overwrite(true); createInfo.set_url(filename); this.files = ctx.get_web().getFolderByServerRelativeUrl(serverRelativeUrl).get_files(); ctx.load(this.files); this.files.add(createInfo); ctx.executeQueryAsync( Function.createDelegate(this, function () { }), Function.createDelegate(this, function (sender, args) { }));
Viendo este código la única duda es de donde obtengo la variable filename, esta varible haciendo uso de la API de HTML5 obtengo los ficheros que se han seleccionado y una vez los tengo los leo y los envio a SharePoint siguiendo este código
var file = document.getElementById("inputFile").files[0]; var bytes = new Uint8Array(file ); var content = new SP.Base64EncodedByteArray(); //base64 encoding for (var b = 0; b < bytes.length; b++) { content.append(bytes[b]); }
Inconvenientes
El principal motivo por el que este forma no se usa, es que tenemos un limite de tamaño de fichero de 1.5 Megas todo lo que sea un fichero de mayo tamaño no se puede subir con lo cual ofrecer esta solución a un cliente es una muy mala practica y una fuente de problemas.
Utilizando el modelo de Objetos de Servidor
Utilizando el modelo de objetos de servidor podemos subir ficheros de cualquier tamaño, para ello la solución que podemos hacer es algo como el siguiente código .NET.
using (SPSite site = new SPSite(SPContext.Current.Site.ID)) { using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID)) { web.AllowUnsafeUpdates = true; SPList list = web.Lists["NameList"]; SPListItem item = list.GetItemById(itemId); int FileLen = file.ContentLength; byte[] input = new byte[FileLen]; // Initialize the stream. System.IO.Stream fileStream = file.InputStream; // Read the file into the byte array. fileStream.Read(input, 0, FileLen); try { item.Attachments.Delete(file.FileName); } catch (Exception) { } item.Attachments.Add(file.FileName, input); item.Update(); web.AllowUnsafeUpdates = false; } }
Inconvenientes
El principal inconveniente que podemos tener es que estemos implementando una solución para Office365 que dado que no podemos tener nada en el servidor NO es una solución que se pueda hacer 🙁
Utiliando el modelo de Objetos de Cliente .NET
En este post ya detalle como hacerlo y como poder aumentar ficheros de gran de tamaño 🙂
Inconveniente
El principal inconveniente que podemos tener es el mismo que con el modelo de objetos en Servidor: Office365. Aquí al contrario que en el modelo de objetos servidor si que se puede hacer uso pero haciendo una solución SandBox y claro hacer una solución SandBox que Microsoft la ha dado por Obsoleta/Deprecated y que quien sabe si en una futura actualización ya no existan y basar nuestro desarrollo en algo que no sabemos el tiempo que le queda no es la mejor opción ni la más elegante. Se podría hacer implementando una APP que realice esta función pero bajo mi punto de vista es como si nos compramos un Ferrari para ir por la montaña 🙂
Utilizando la API Rest
He dejado la opción buena y bonita para el final 🙂 La API Rest de SharePoint creo que se puede mejorar en bastantes aspectos pero por ejemplo para el tema de ficheros la solución es perfecta. Porque digo perfecta porque es valida para todos los entornos (Onpremise, Online) y porque podemos subir ficheros de una capacidad máxima de 2 GB como :
function ProcessUpload(fileInput, docLibraryName, folderName,h,j) { var reader = new FileReader(); reader.readAsArrayBuffer(fileInput); reader.onload = function (result) { PerformUpload(docLibraryName, fileInput.name, folderName, result.target.result,h,j); }; } function PerformUpload(libraryName, fileName, folderName, fileData,i,j) { var url; url= targetSiteUrl +"/_api/web/lists/getByTitle('"+libraryName +"')/RootFolder/folders('"+folderName + "')/files/add(url='" + fileName +"',overwrite='true')" debugger; $.ajax({ url: url, type: "POST", data: fileData, processData: false, contentType: false, headers: { "accept": "application/json;odata=verbose", "X-RequestDigest": $("#__REQUESTDIGEST").val(), "content-length": fileData.byteLength }, success: function (data) { alert("File Upload Exit"); }, error: function (err) { alert("Error update item"); } }); }
Observaciones
En este punto de subir el fichero de esta forma tenemos que tener en cuenta dos valores que son el processData y el contentType si estos valores no los establecemos a False, el fichero lo subiremos pero en el momento que lo vayamos a abrir nos indicará que esta corrupto. Este motivo es porque el fichero lo interpretara como binario y por lo tanto no lo podemos abrir. Otro aspecto que tenemos que tener en cuenta es que en esta opción no hemos tenido que leer el fichero el valor que obtenemos directamente no hace falta leerlo, lo cual hace que sea mucho más rápido ya que nos evitamos hacer dos lecturas.
Inconvenientes
Para hacer esta funcionalidad con JavaScript es necesario que utilicemos un servidor moderno IE10, la última versión Chrome y Mozilla porque si no interpreta HTML5 no podemos obtener los ficheros que se han seleccionado.
Conclusiones
En SharePoint tiene una ventaja que en ocasiones puede ser una lastre, es que se pueden hacer las cosas de muchas maneras. Esto pude hacer que podamos seleccionar la opción que mejor se adapte a nuestro perfil o nuestro conocimiento pero esto puede provocar que no se seleccione la mejor opción.
Referencias
http://www.shillier.com/archive/2013/03/26/uploading-files-in-sharepoint-2013-using-csom-and-rest.aspx
http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax