JavaScript: Base64 Daten an ASMX senden
avatar

In einem meiner Projekte, gab es kürzlich die Anforderung, Dateien aus einer beliebigen Quelle im Web an mehrere Ziele im SharePoint zu senden. Die Lösung musste ohne serverseitigen Code funktionieren. Ich hatte zu diesem Thema einen einfachen Proof Of Concept durchgeführt, der in diesem Artikel erklärt wird.

Der einfachste Weg, eine Datei an mehrere SharePoint Bibliotheken zu schicken ist nach wie vor der Copx.asmx-Webservice. Zwar geht das auch mit JSOM; die Performanz ist allerdings nicht optimal, da die Datei für jedes Ziel neu gesendet werden muss.

 

Der POC

In dem hier beschriebenen Beispiel wird eine Quelldatei geladen, bas64-transformiert und anschließend an den copy.asmx gesendet.

In dem Eingabefeld “Quelle” kann die URL einer beliebigen Datei definiert werden; ob nun im SharePoint oder nicht. Darunter können die Ziel-URLs (SharePoint) kommasepariert angegeben werden. In dem dritten  Feld “Titel” kann das entsprechende Metadatum für die neuen Listeneinträge gesetzt werden.

image

Per Klick auf die Schaltfläche “OK” startet der Verteilervorgang. In einer produktiven Lösung sollte die UI natürlich mehr hermachen! Smile

 

Der Code

Die Funktion “readFile” holt die Datei (BLOB) per XMLHttpRequest und konvertiert diese anschließend mit einem FileReader zu Base64. Mit der Methode “sendToService” wird die Datei anschließend auf die Ziele verteilt.

<script type="text/javascript">

    var Component = (function () {
       
        return {
            readFile: function (fileUrl, targetUrl, title) {
 
                    var xhr = new XMLHttpRequest();
                    xhr.open('GET', fileUrl, true);
                    xhr.responseType = 'blob';
                    xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
                    xhr.onload = function (e) {
                        if (this.status == 200) {
                            var blob = new Blob([this.response]);
                            // convert blob to base64
                            var reader = new FileReader();
                            reader.onload = function () {
                                var dataUrl = reader.result;
                                var base64 = dataUrl.split(',')[1];
                                Component.sendToService(base64, fileUrl, targetUrl, title)
                            };
                            reader.readAsDataURL(blob);

                        } else {
                            alert('Unable to copy file.')
                        }
                    };
                    xhr.send();
            },
            sendToService: function (binary, sourceUrl, targetUrls, title) {

                var urls = targetUrls.split(',');

                var soapEnv='<?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>'+sourceUrl+'</SourceUrl>'
                    +'    <DestinationUrls>';

                    for(i=0; i< urls.length; i++){
                         soapEnv= soapEnv +'  <string>'+urls[i]+'</string>'
                    }
                   
                    soapEnv= soapEnv +'    </DestinationUrls>'
                    +'    <Fields>'
                    +'        <FieldInformation Type="File" />'
                    +'        <FieldInformation Type="Text" DisplayName="Title" InternalName="Title" Id="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Value="'+title+'" />'
                    +'    </Fields>'
                    +'    <Stream>' + binary + '</Stream>'
                    +'    </CopyIntoItems>'
                    +'</soap:Body>'
                    +'</soap:Envelope>';           
                
                $.ajax({
                    url: "http://sp2016.spdev.local/sites/pub1/_vti_bin/copy.asmx",
                    contentType: "text/xml",
                    type: "POST",
                    dataType: "xml",
                    data: soapEnv,
                    beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/CopyIntoItems'); },
                    contentType: "text/xml; charset=\"utf-8\""
                })
            .done(function (data) {
                console.log('Hurra!');
            })
            .error(function () {
                alert("Request failed: " + arguments[0].responseText);
            });
            }
        };
    })(Component || {});


    function start(src, dest, title) { 
        if(src != ''){
             Component.readFile(src, dest, title);
        }
    }

    //Injecting jQuery
    function load() {
        //use this to trigger “copy file” on page load
        loadScript(_spPageContextInfo.siteAbsoluteUrl + "/Style%20Library/jquery-1.10.2.min.js", start("", "",""));
    }

    function loadScript(url, callback) {
        // Adding the script tag to the head as suggested before
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url;

        script.onload = callback;

        // Fire the loading
        head.appendChild(script);
    }

    (function () {
        if (typeof (_spBodyOnLoadFunctions) === 'undefined' || _spBodyOnLoadFunctions === null) {
            return;
        }

        _spBodyOnLoadFunctions.push(function () {
            ExecuteOrDelayUntilScriptLoaded(load(), 'SP.init.js');
        });
    })();


</script>

<div>
    <div>
        <label for="file-source-url"  >Quelle:</label>
        <input id="file-source-url" type="text"  style="width:500px" /> 
    </div>
    <div>
        <label for="file-dest-url" >Ziele (1,2,..):</label>
        <input id="file-dest-url" type="text" style="width:800px" /> 
    </div>
    <div>
        <label for="file-dest-title" >Titel:</label>
        <input id="file-dest-title" type="text" style="width:500px" /> 
    </div>
    <button onclick="start(document.getElementById('file-source-url').value, document.getElementById('file-dest-url').value, document.getElementById('file-dest-title').value);">OK</button>
</div>

Der Code außerhalb vom Modul “Component” ist lediglich Overhead, um die Lösung in einem Content Editor Webpart zu starten.

 

Das Ergebnis

Im nachfolgenden Screenshot wird die Datei “…/Demo1/Test.pdf” an die  zwei Ziele “…/Demo1/Test_neu.pdf” und “…/Demo2/Test_neu.pdf” verteilt. Der Titel wird dabei auf “Neue Dateien” gesetzt.

image 

In beiden Bibliotheken ist nun die Kopie der Quelldatei zu finden. Ein Blick in die Eigenschaften zeigt, dass auch der Titel richtig gesetzt wurde.

image

Ich hoffe der Code kann Euch weiterhelfen!

Schreibe einen Kommentar