Author: andre
Publication Date: 2/8/2013 14:54
1. UploadHooks in general
...here we go ...brief.....
* ... processed on new media creation or changing a picture/file of a FirstSpirit medium
(yes, FirstSpirit-5 does support setting preview thumbnails for media of type FirstSpirit.File)
* ... process before and/or after an upload to the FirstSpirit-Server was triggered by the user or a FirstSpirit-API-Call
@see implementation interface: http://www.e-spirit.com/odfs50/dev/?de/espirit/firstspirit/service/mediamanagement/UploadHook.html
or an upload has been aborted by an UploadHook throwing an UploadRejectedException in this case the Hooks uploadAborted method will be called
to give the Hook a chance of cleaning something.
some use cases out of many...
* call any thirdparty- or custom FirstSpirit-Module-Component -service e.g scan for virus before uploading a medium to the FirstSpirit-Server
* generate custom thumbnails e.g. for PDF Files
* extract meta data information (e.g. image exif data) and assign/write them to the meta data of a FirstSpirit media.
for this case FirstSpirit provides a deffault ExifUploadHook implementation sprinkled with a small exif-developer-api
for exif data processing and formatting able to extract any simple
(e.g. image orientation '...extract image exif orientation information and rotate the image auto-magically' , timestamps ...) exif types
as well complex type like Geolocation information.
Dev-API:
in addition to the default ExifUploadHook-Implementation it is possible to register custom additional ExifHook(s)
@see Release notes chapter 7.7 for some FirstSpirit exif documentation - usages in templates and basic concepts
http://www.e-spirit.com/odfs50/en/weiterfuehrende_themen/exif_daten/exif_daten_1.html?community
* reject uploads to the FirstSpirit-Server for any desired cases throwing an UploadRejectedException (this needs to be done in the pre*-Method of the Hook)
2. ... some details - an example PDF-Thumbnail-Hook implementation (use PDFRenderer library - Source License: LGPL-2.1)
* registering the hook as FirstSpirit-Module (module descriptor)
-------Module descriptor ------------------------------------------------------------------------------------------
<module>
<name>FirstSpirit PDF Preview-Image UploadHook Example</name>
<version>@VERSION@</version>
<description>FirstSpirit PDF Preview-Image UploadHook example implementation.</description>
<vendor>e-Spirit AG</vendor>
<components>
<public>
<name>PDF_THUMBNAIL_UPLOADHOOK</name>
<description>FirstSpirit PDF Preview-Image UploadHook example implementation.</description>
<class>de.espirit.firstspirit.opt.example.PdfThumbnailHookExample</class>
<resources>
<resource scope="server">lib/fs-example_pdfthumbnailhook.jar</resource>
<resource scope="server">lib/PDFRenderer-0.9.0.jar</resource>
</resources>
</public>
</components>
</module>
-----------------------------------------------------------------------------------------------------------------
...at least some java
---------------PdfThumbnailHookExample.java ---------------------------------------------------------------------
public class PdfThumbnailHookExample implements UploadHook {
public void preProcess(@NotNull final BaseContext baseContext, @NotNull final Media media, @NotNull final File file, @NotNull final InputStream inputStream, final long length) throws UploadRejectedException, IOException {
//nothing to do
}
public void preProcess(@NotNull final BaseContext baseContext, @NotNull final Media media, @NotNull final Picture picture, final Resolution resolution, @NotNull final InputStream inputStream, final long length) throws UploadRejectedException, IOException {
//nothing to do
}
public void postProcess(@NotNull final BaseContext baseContext, @NotNull final Media media, @NotNull final File file, final long length) {
final MimeType mimeType = file.getMimeType();
if (mimeType == null) {
return;
}
final String extension = file.getExtension();
if (extension != null && !"pdf".equals(extension.toLowerCase(Locale.ENGLISH))) {
return;
}
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
final Image image = createImage(baseContext, inputStream, (int) file.getSize());
if (image == null) {
baseContext.logWarning("PDF image generation failed.");
}
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write((RenderedImage) image, "png", byteArrayOutputStream);
final byte[] bytes = byteArrayOutputStream.toByteArray();
if (bytes.length > 0) {
file.setPreviewImage(bytes);
}
} catch (IOException e) {
baseContext.logError("PDF image generation failed.", e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignore) {
}
}
}
}
public void postProcess(@NotNull final BaseContext baseContext, @NotNull final Media media, @NotNull final Picture picture, final long length) {
//nothing to do
}
public void uploadAborted(@NotNull final BaseContext baseContext, @NotNull final Media media, @NotNull final MediaElement mediaElement) {
//nothing to do
}
@Nullable
private static Image createImage(final BaseContext baseContext, final InputStream stream, final int size) throws IOException {
final byte[] bytes = readFromStream(stream, size);
final ByteBuffer buffer = ByteBuffer.allocateDirect(size);
buffer.put(bytes);
final PDFFile pdfFile = new PDFFile(buffer);
final int pages = pdfFile.getNumPages();
if (pages < 1) {
baseContext.logWarning("Minimum of one pdf page is required to render an image.");
return null;
}
final PDFPage page = pdfFile.getPage(0);
return page.getImage((int) page.getWidth(), (int) page.getHeight(), page.getBBox(), null, true, true);
}
private static byte[] readFromStream(final InputStream in, final int size) throws IOException {
final byte[] bytes = new byte[size];
try {
int offset = 0;
do {
final int len = in.read(bytes, offset, bytes.length - offset);
if (len == -1) {
throw new IllegalStateException("buffer underflow");
}
offset += len;
} while (offset < bytes.length);
} finally {
in.close();
}
return bytes;
}
}
not much ...isn't it?
----------------------------------------------------------------------------------------------------
The PdfThumbnailHookExample.java captures always the first page of the pdf,
may be providing some settings (...which pdf page to render) through the media meta data could be useful.
feel free to ask your e-Spirit contact to get the full example hook implementation.
There's also an exif_example_project.tar.gz which you could ask our help desk for.
NOTE: keep in mind an UploadHook may run in the FirstSpirit JavaClient and FirstSpirit WebEdit.
Tags: exif, exifhook, exifuploadhook, file, firstspirit-uploadhooks, pdf-preview-image, uploadhook, uploadhooks
Kommentare
6 Kommentare
Hallo Andre,
ist es irgendwie möglich den Scope des Upload Hooks zu begrenzen ohne jedes mal das Projekt abzufragen ?
Grüße, Kai
hallo kai,
...der UploadHook wird bei upload vom medien aufgerufen und medien sind ja im prinzip projektgebunden....was genau meinst du mit "projekt abfragen"? bzw. wie und warum fragst du vom hook das projekt an? was ist denn der use-case?
--
andre
Hallo Andre, ich möchte die funktionalität des Upload Hooks nur in einem bestimmten Projekt verwenden. Wenn sich nun aber mehr wie ein Projekt auf meinem Server befindet funktioniert der Upload Hook ja in den anderen Projekten genauso. Das ist unter umständen nicht erwünscht.
Mit "Projekt abfragen" meine ich eine simple Verzweigung in der abgefragt wird in welches Projekt "geuploadet" wird.
Grüße, Kai
ah, ok, ...nein ,das geht leider nicht. evtl. stellst du einen Feature-REquest: ProjectBasedUploadHook o.ä.
--
gruesse
andre
Hallo André.
Genial! Von dieser Art Hook bräuchte es in FirstSpirit noch viel mehr!!!!!
Der Hook greift beim Neuanlegen eines Bildes und beim Anlegen eines Bildausschnittes.
Letzteres wollte ich mir zu nutzen machen. Wenn der Redakteur einen Bildeausschnitt anlegt, wollte ich mit Hilfe der Crop Daten die Koordinaten des Rechtecks auslesen und weiterverarbeiten.
Nun ist es jedoch so, dass nach Klick auf "Übernehmen" im Bildausschnittdialog der Hook angesprochen wird. Ich bekomme dann die Höhe und Breite des Zuschnittes, aber nicht die Crop Daten da diese Daten vermutlich zu diesem Zeitpunkt noch nicht erstellt sind.
Gibt es irgend einen Weg wie ich doch an die Crop Daten kommen kann?
Eigentlich bräuchte ich ja nur den linken oberen Punkt des Ausschnittes. Den Rest bekomme ich über die Höhe und Breite. Kriege ich diesen Punkt vielleicht wo anders noch her?
Gruß,
Daniel
Hallo André,
gibt es eine Möglichkeit im Upload-Hook selbst, in Abhängigkeit vom auslösenden Context, eine Behandlung auszuführen? Etwa um sicherzustellen, dass nur im Fall eines Aufrufs aus dem ContentCreator das implementierte Upload-Hook-Verhalten anzustoßen.
Etwa:
Im Moment zieht das nicht, da der Hook selbst nicht im WEBEDIT-Context läuft! Nach meinem Verständnis wäre auch dafür wieder ein FeatureRequest notwendig. Richtig?
Bitte melden Sie sich an, um einen Kommentar zu hinterlassen.