SebastianStieme
Returning Observer

Import von PDF-Dateien per Script

Jump to solution

Hallo  FirstSpirit Community.

Ich stehe vor folgender Aufgabe. Ich generiere einen Newsletter. Dieser Newsletter hat einen PDF-Ausgabekanal. Im Generirungs-Auftrag auf dem Server habe ich nun noch ein neues Script angelegt. Das Script soll folgende Aktion durchführen.

Ermittlung des Pfades zu den generierten PDF Dateien auf dem FirstSpirit Server (das habe ich hin bekommen)

Hochladen dieser generierten PDF Datei in die Medienverwaltung. Hier hakt es leider. Im folgenden einmal mein bisherieger Stand (ohne das Ermitteln der Dateipfade)

File file = new File("c:/firstSpirit/web/staging/de_1/newsletter.pdf");

StoreAgent storeAgent = context.requestSpecialist(StoreAgent.TYPE);

MediaStoreRoot mediaStore = (MediaStoreRoot) storeAgent.getStore(Store.Type.MEDIASTORE);

IDProvider storeElement = null;

try {

    storeElement = mediaStore.createMedia(file.getName(), file.getName(), Media.FILE, false);

} catch (DuplicateReferenceNameException e) {

    context.logInfo(e.getMessage());

} catch (LockException e) {

    context.logInfo(e.getMessage());

} catch (ElementDeletedException e) {

    context.logInfo(e.getMessage());

}

Media media = (Media) storeElement;

context.logInfo(String.format("<h3>uploading '%s' --> '%s'</h3>", file.getAbsolutePath(), media.getReferenceName()));

try {

    FileInputStream fis = new FileInputStream(file);

 

    InputStreamReader inputStreamReader = new InputStreamReader(fis, "utf-8");

    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

    StringBuilder stringBuilder = new StringBuilder();

    String line;

    while ((line = bufferedReader.readLine()) != null) {

        stringBuilder.append(line + "\n");

    }

    String fileContentAsString = stringBuilder.toString();

    ByteArrayInputStream in = new ByteArrayInputStream(fileContentAsString.getBytes());

    media.setLock(true);

    de.espirit.firstspirit.access.store.mediastore.File fileOfMedia = media.getFile(null);

    fileOfMedia.setFile(fileContentAsString.getBytes().length, in, "pdf");

    //fileOfMedia.setEncoding("utf-8");

    //media.setParseFile(true);

    media.save();

} catch (IOException e) {

    context.logInfo(String.format("Can not read '%s' from disk. \n %s", file.getAbsolutePath(), e));

} catch (LockException e) {

    context.logInfo(String.format("Can not lock Storelement '%s'. \n %s", storeElement.getReferenceName(), e));

} catch (ElementDeletedException e) {

    context.logInfo(String.format("Can not lock Storelement '%s'. Element is probably deleted. \n %s", storeElement.getReferenceName(), e));

} finally {

    try {

        media.setLock(false);

    } catch (LockException e) {

        context.logInfo(String.format("Can not unlock Storelement '%s'. \n %s", storeElement.getReferenceName(), e));

    } catch (ElementDeletedException e) {

        context.logInfo(String.format("Can not unlock Storelement '%s'. Element is probably deleted. \n %s", storeElement.getReferenceName(), e));

    }

}

Es wird erfolgreich ein neues Medium angelegt und es wird auch der Inhalt der PDF hineingeschrieben. Scheinbar aber mit kleinen Encoding Fehlern oder so?!? Die original Datei ist wenn ich sie von Hand in die Medienverwaltung hochlade 6kb groß. Die vom Scrip generierte Datei aber 8kb.

Ich habe beide Dateien einmal diesem Post angefügt.

Hat hier jemand einen Hinweis was hier falsch läuft?

Bzw. gibt es vielleicht andere  Ansätze, wie ich per Script die PDF Datei in die Medienverwaltung importiert bekomme?

Vielen Dank für eure Hilfe.

Gruß

Sebastian

1 Solution

Accepted Solutions

Hallo Sebastian,

naja, Du übergibst ja immer noch die Länge des Strings (bzw. die Byte-Anzahl einer in diesem Fall "zufälligen" Codierung) 😉

Ich meinte eher das hier:

...

try {
    FileInputStream fis = new FileInputStream(file);
    media.setLock(true);
    de.espirit.firstspirit.access.store.mediastore.File fileOfMedia = media.getFile(null);
    fileOfMedia.setFile(file.length(), fis, "pdf");
    media.save();
} catch (IOException e) {

...

Übrigens: Je nach Anwendungsfall solltest Du ggf. die Mediafolder.createFile(...)-Methode verwenden, die - falls es ein Medium mit diesem Referenznamen schon gibt - automatisch einen entsprechend abgewandelten (_1, _2 usw.) erzeugt.

Viele Grüße

Michael

View solution in original post

5 Replies
mbergmann
Crownpeak employee

Hallo Sebastian,

mir ist nicht klar wozu der Umweg über den String notwendig sein soll. Warum arbeitest Du im setFile(...) nicht direkt mit dem InputStream des Files?

Soweit ich weiß ist das Thema PDF+Encoding auch nicht unbedingt trivial, einfach davon auszugehen dass hier ein als UTF-8 encodeter Text bzw. überhaupt ein einziges dateiweites Encoding vorliegt, muss nicht unbedingt stimmen 😉

Und die methode String.getBytes() liefert die Bytes immer im System-Default-Encoding - ein String selbst hat ja kein Encoding.

Viele Grüße

Michael

0 Kudos

Hallo Michael,

also wenn ich der Methode setFile() direkt den FileInputStream übergebe gibt es eine Fehlermeldung. Scheinbar kommt die Methode nicht an den Inhalt der Datei heran.

FileInputStream fis = new FileInputStream(file);

...

fileOfMedia.setFile(fileContentAsString.getBytes().length, fis, "pdf");

Hier noch der dazugehörige StackTrace:

INFO  13.05.2016 09:00:14.308 (de.espirit.firstspirit.impl.access.ScriptContextImpl): <h3>uploading 'C:\Program Files (x86)\FirstSpirit5\web\fs5staging\2004\3468\de_1\newsletter\testnewsletter\newsletter_1_4032.pdf' --> 'media:newsletter_1_4032.pdf'</h3>

INFO  13.05.2016 09:00:14.314 (de.espirit.firstspirit.impl.access.ScriptContextImpl): fileContentAsString.getBytes().length: 8421

INFO  13.05.2016 09:00:14.314 (de.espirit.firstspirit.impl.access.ScriptContextImpl): fis: java.io.FileInputStream@533ee2cf

ERROR 13.05.2016 09:00:14.321{dNR=} (de.espirit.firstspirit.server.scheduler.ScriptTaskExecutor): error during script execution : de.espirit.firstspirit.access.script.ExecutionException: Method Invocation fileOfMedia.setFile : at Line: 140 : in file: inline evaluation of: ``__execute() { // Imports /////////////////////////////////////////////////////// . . . '' : fileOfMedia .setFile ( fileContentAsString .getBytes ( ) .length , fis , "pdf" )

Target exception: java.lang.IllegalArgumentException: Input length mismatch: 8421 != 0

at line 140

de.espirit.firstspirit.access.script.ExecutionException: Method Invocation fileOfMedia.setFile : at Line: 140 : in file: inline evaluation of: ``__execute() { // Imports /////////////////////////////////////////////////////// . . . '' : fileOfMedia .setFile ( fileContentAsString .getBytes ( ) .length , fis , "pdf" )

Target exception: java.lang.IllegalArgumentException: Input length mismatch: 8421 != 0

at line 140

          at de.espirit.firstspirit.server.script.BeanshellScriptEngine$BeanshellExecutable.execute(BeanshellScriptEngine.java:109)

          at de.espirit.firstspirit.common.ScriptUtil.execute(ScriptUtil.java:106)

          at de.espirit.firstspirit.server.scheduler.ScriptTaskExecutor.run(ScriptTaskExecutor.java:134)

          at de.espirit.firstspirit.server.scheduler.ScheduleManagerImpl$TaskCallable.executeLocal(ScheduleManagerImpl.java:2258)

          at de.espirit.firstspirit.server.scheduler.ScheduleManagerImpl$TaskCallable.executeLocal(ScheduleManagerImpl.java:2241)

          at de.espirit.firstspirit.server.scheduler.ScheduleManagerImpl$TaskCallable.call(ScheduleManagerImpl.java:2164)

          at de.espirit.firstspirit.server.ExecutionManagerImpl$ExtendedCallable.call(ExecutionManagerImpl.java:600)

          at java.util.concurrent.FutureTask.run(FutureTask.java:266)

          at de.espirit.common.util.BoundedExecutorService$RunnableWrapper.run(BoundedExecutorService.java:436)

          at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

          at java.util.concurrent.FutureTask.run(FutureTask.java:266)

          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

          at java.lang.Thread.run(Thread.java:745)

          at de.espirit.common.util.SuspendableThread.run(SuspendableThread.java:55)

Caused by: java.lang.IllegalArgumentException: Input length mismatch: 8421 != 0

          at de.espirit.storage.StorageUtil.toByteArrayBuffer(StorageUtil.java:145)

          at de.espirit.storage.backend.bdb5.BerkeleyDbBackend.setContent(BerkeleyDbBackend.java:1046)

          at de.espirit.storage.backend.bdb5.BerkeleyDbBackend.setFileContent(BerkeleyDbBackend.java:762)

          at de.espirit.storage.Repository.setFileContent(Repository.java:1104)

          at de.espirit.firstspirit.storage.RepositoryManagerImpl.setContent(RepositoryManagerImpl.java:1428)

          at de.espirit.firstspirit.server.mediamanagement.MediaManagerImpl.uploadFile(MediaManagerImpl.java:273)

          at de.espirit.firstspirit.store.access.mediastore.FileImpl.uploadFile(FileImpl.java:288)

          at de.espirit.firstspirit.store.access.mediastore.FileImpl.setFile(FileImpl.java:144)

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

          at java.lang.reflect.Method.invoke(Method.java:498)

          at bsh.Reflect.invokeMethod(Reflect.java:166)

          at bsh.Reflect.invokeObjectMethod(Reflect.java:99)

          at bsh.Name.invokeMethod(Name.java:858)

          at bsh.BSHMethodInvocation.eval(BSHMethodInvocation.java:75)

          at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:102)

          at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:47)

          at bsh.BSHBlock.evalBlock(BSHBlock.java:130)

          at bsh.BSHBlock.eval(BSHBlock.java:80)

          at bsh.BSHBlock.eval(BSHBlock.java:46)

          at bsh.BSHTryStatement.eval(BSHTryStatement.java:88)

          at bsh.BSHBlock.evalBlock(BSHBlock.java:130)

          at bsh.BSHBlock.eval(BSHBlock.java:80)

          at bsh.BshMethod.invokeImpl(BshMethod.java:371)

          at bsh.BshMethod.invoke(BshMethod.java:267)

          at bsh.BshMethod.invoke(BshMethod.java:170)

          at bsh.PreparsedScript.invoke(PreparsedScript.java:66)

          at de.espirit.firstspirit.server.script.BeanshellScriptEngine$BeanshellExecutable.execute(BeanshellScriptEngine.java:100)

          ... 14 more

0 Kudos

Hallo Sebastian,

naja, Du übergibst ja immer noch die Länge des Strings (bzw. die Byte-Anzahl einer in diesem Fall "zufälligen" Codierung) 😉

Ich meinte eher das hier:

...

try {
    FileInputStream fis = new FileInputStream(file);
    media.setLock(true);
    de.espirit.firstspirit.access.store.mediastore.File fileOfMedia = media.getFile(null);
    fileOfMedia.setFile(file.length(), fis, "pdf");
    media.save();
} catch (IOException e) {

...

Übrigens: Je nach Anwendungsfall solltest Du ggf. die Mediafolder.createFile(...)-Methode verwenden, die - falls es ein Medium mit diesem Referenznamen schon gibt - automatisch einen entsprechend abgewandelten (_1, _2 usw.) erzeugt.

Viele Grüße

Michael

Hallo Michael,

vielen vielen Dank. Das hat nun funktioniert.

Das ich ursprünglich den Umweg über den String gemacht hatte, lag daran das ich den Teil aus einem anderen Script per Copy&Paste übernommen hatte ; ) ... in dem Script wurde der String aber auch tatsächlich noch manipuliert, weshalb das an der Stelle sicher Sinn gemacht hat.

Du liegst aber natürlich Gold richtig, das das in meinem Fall keinen Sinn macht.

Wie gesagt, vielen Dank, deine Hilfe hat mir sehr geholfen.

Gruß

Sebastian

0 Kudos

Vielleicht braucht der Eine oder Andere es ja noch, ... hier das gesamte Script:

/*******************

*** Beschreibung ***

*******************/

// Autor: Sebastian Stiemer (adesso AG)

//

// Parameter:

// p_newsletterArchivMediaFolderUid (Pflicht) - in welchem MediaOrdner (Referenzname) sollen die NewsletterPDFs importiert werden? z.B. "newsletter_archiv"

// p_pdf_channel_nr (Pflicht) - Welche Nr hat der PDF Ausgabekanal in dem entsprechenden Projekt? z.B. "1"

//

// Das im zuvor ausgeführten Generierungstask generiert Newsletter-PDFs werden in

// die Medienverwaltung des Projekts importiert

// 1. es werden die Pfade der generierten PDFs in allen Sprachen im Generierungsordner des FiSp-Servers ermittelt

// 2. es wird ein neues sprachabhängiges Medium angelegt, bzw. sollte es das Medium schon geben, wird das bestehende genommen

// 3. Der Inhalt des Mediums wird mit den sprachabhängigen generierten PDF-Dateien befüllt

// 4. der Newsletter-Archiv-Ordner wird rekursiv freigegeben

//

// in mindestens einem Template, welches im Generate Task generiert wird, muss in einen Ausgabekanal folgende Zeile:

// $CMS_SET(void, #global.scheduleContext.setProperty("generationContext", #global.generationContext))$

// um dann hier im Script an den generationContext zu gelangen

//

// es wird eine eigene Verbindung für das Script benötigt

/**************

*** Imports ***

**************/

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import java.util.Map.Entry;

import de.espirit.firstspirit.access.AccessUtil;

import de.espirit.firstspirit.access.GenerationContext;

import de.espirit.firstspirit.access.Language;

import de.espirit.firstspirit.access.schedule.GenerateTask;

import de.espirit.firstspirit.access.schedule.ScheduleContext;

import de.espirit.firstspirit.access.schedule.ScheduleTask;

import de.espirit.firstspirit.access.schedule.ScriptTask;

import de.espirit.firstspirit.access.store.ElementDeletedException;

import de.espirit.firstspirit.access.store.IDProvider;

import de.espirit.firstspirit.access.store.LockException;

import de.espirit.firstspirit.access.store.Store;

import de.espirit.firstspirit.access.store.mediastore.Media;

import de.espirit.firstspirit.access.store.mediastore.MediaFolder;

import de.espirit.firstspirit.access.store.mediastore.MediaStoreRoot;

import de.espirit.firstspirit.access.store.sitestore.PageRef;

import de.espirit.firstspirit.access.store.sitestore.SiteStoreFolder;

import de.espirit.firstspirit.agency.StoreAgent;

/**************

*** Methods ***

**************/

   

// guckt im aktuellen Auftrag ob es genau 1. Teilgenerierungstask gibt und gibt diesen zurück

static GenerateTask getPartialGenerateTask(){

    List<ScheduleTask> scheduleTasks = context.getTask().getScheduleEntry().getTasks();

    boolean partialGenerateTaskFound = false;

    GenerateTask generateTask = null;

    for (ScheduleTask scheduleTask : scheduleTasks) {

        if(scheduleTask instanceof GenerateTask && (((GenerateTask) scheduleTask).getType() == GenerateTask.Type.Partial)) {

            if (!partialGenerateTaskFound) {

                generateTask = (GenerateTask) scheduleTask;

                partialGenerateTaskFound = true;

            } else {

                throw new IllegalArgumentException("There is more then one partly-generation-task in this shedule-entry");

            }

        }

    }

    return generateTask;

}

// holt einen Scriptparaemter

static String getScriptParameter(String key, Boolean required) {

   

    String paramValue = null;

    ScriptTask task = (ScriptTask) context.getTask();

    for (Entry param : task.getParameters()) {

        if(param.getKey().equals(key)) {

            paramValue = (String) param.getValue();

            break;

        }

    }

    if(required && paramValue == null){

        throw new IllegalArgumentException("Script-Property with key '" + key + "' cant be empty!");

    }

    return paramValue;

}

/**************

*** Main ***

**************/

// generationContext holen

GenerateTask generateTask = getPartialGenerateTask();       

GenerationContext generationContext = (GenerationContext) context.getProperty("generationContext");       

// Script-Parameter

String p_newsletterArchivMediaFolderUid = getScriptParameter("p_newsletterArchivMediaFolderUid", true);

String p_pdf_channel_nr = getScriptParameter("p_pdf_channel_nr", true);

if(p_pdf_channel_nr.equals("0")) {

    p_pdf_channel_nr = "";

}

else {

    p_pdf_channel_nr = "_" + p_pdf_channel_nr;

}

// PageRef des Newsletters

PageRef newsletterPageRef = (PageRef) generateTask.getStartNodes().get(0);

// Alle Projekt-Sprachen

List<Language> projectLanguages = context.getProject().getLanguages();

// Ermitteln aller ParentFolders ausgehend vom Newsletter-PageRef in der Seitenstruktur

SiteStoreFolder parentFolder = newsletterPageRef.getParentFolder();

String parentFolders = "";       

while (!"root".equals(parentFolder.getUid())) {

    parentFolders = parentFolder.getUid() + "/" + parentFolders;

    parentFolder = parentFolder.getParentFolder();

}

// Zusammenbau der Pfade zum Newsletter-PDF für jede Sprache

ArrayList pdfFiles = new ArrayList();

for (Language language : projectLanguages) {

    pdfFiles.add(generationContext.getBasePath() + language.getLocale().getLanguage() + p_pdf_channel_nr + "/" + parentFolders + newsletterPageRef.getFilename() + "_" + newsletterPageRef.getContent2Params().getFilterParams().get("newsletterId") + ".pdf");

}

// Speichern der PDF Datei im MediaStore ///////////

File file = new File((String) pdfFiles.get(0));

StoreAgent storeAgent = context.requestSpecialist(StoreAgent.TYPE);

MediaStoreRoot mediaStore = (MediaStoreRoot) storeAgent.getStore(Store.Type.MEDIASTORE);

IDProvider storeElement = null;

IDProvider newsletterArchiv = mediaStore.getStoreElement(p_newsletterArchivMediaFolderUid, IDProvider.UidType.MEDIASTORE_FOLDER);

// wurde die PDF Datei schon einmal angelegt? Wenn ja Update, wenn nein wird ein neues Medium angelegt

storeElement = mediaStore.getStoreElement(file.getName(), IDProvider.UidType.MEDIASTORE_LEAF);

if(storeElement == null) {

    try {

        storeElement = ((MediaFolder) newsletterArchiv).createMedia(file.getName(), file.getName(), Media.FILE, true);

    } catch (Exception e) {

        context.logWarning(e.getMessage());

    }

}

// der Inhalt des Mediums wird mit den sprachabhängigen PDF-Dateien gefüllt

Media media = (Media) storeElement;

context.logInfo(String.format("uploading '%s' --> '%s'", file.getAbsolutePath(), media.getReferenceName()));

try {

    media.setLock(true);

    int i = 0;

    for ( Language language : projectLanguages) {

        file = new File((String) pdfFiles.get(i));

        i++;

       

        // Prüfung op die Datei (in der aktuellen Sprache) auch wirklich generiert wurde. falls nicht, dann ab zur nächsten Sprache

        if(!file.isFile()) {

            continue;

        }

       

        FileInputStream fis = new FileInputStream(file);

        de.espirit.firstspirit.access.store.mediastore.File fileOfMedia = media.getFile(language);   

        fileOfMedia.setFile(file.length(), fis, "pdf");       

    }

    media.save();

} catch (IOException e) {

    context.logWarning(String.format("Can not read '%s' from disk. \n %s", file.getAbsolutePath(), e));

} catch (LockException e) {

    context.logWarning(String.format("Can not lock Storelement '%s'. \n %s", storeElement.getReferenceName(), e));

} catch (ElementDeletedException e) {

    context.logWarning(String.format("Can not lock Storelement '%s'. Element is probably deleted. \n %s", storeElement.getReferenceName(), e));

} finally {

    try {

        media.release();

        media.setLock(false);

    } catch (LockException e) {

        context.logWarning(String.format("Can not unlock Storelement '%s'. \n %s", storeElement.getReferenceName(), e));

    } catch (ElementDeletedException e) {

        context.logWarning(String.format("Can not unlock Storelement '%s'. Element is probably deleted. \n %s", storeElement.getReferenceName(), e));

    }

   

    // newsletterArchiv rekursiv freigeben

    try {

        newsletterArchiv.setLock(true);

        newsletterArchiv.release();

        newsletterArchiv.setLock(false);

    } catch (LockException e) {

        context.logWarning(String.format("Can not unlock Storelement '%s'. \n %s", newsletterArchiv.getReferenceName(), e));

    } catch (ElementDeletedException e) {

        context.logWarning(String.format("Can not unlock Storelement '%s'. Element is probably deleted. \n %s", newsletterArchiv.getReferenceName(), e));

    }

    AccessUtil.release(newsletterArchiv, false, true, true, IDProvider.DependentReleaseType.NO_DEPENDENT_RELEASE, "Script: sc_archiveNewsletterPDF > release");

}