Zum Hauptinhalt gehen

UploadHook - remove EXIF information of an image on upload

Kommentare

5 Kommentare

  • Zendesk API User
    Author: Windmüller - 10/18/2023 7:46

    Hi Timo! Thanks for reaching out and providing that much debug information.

    The first issue you discovered is the multiple execution of the preProcess method. This looks like a bug and I am going to create an internal ticket for that.

    That said, your current approach is not going to work because the InputStream passed to the preProcess method cannot be modified. In fact, each UploadHook receives a new instance of it. This is why you see the 180kb image over and over again.

    In order to accomplish your goal, you can implement postProcess and call Picture#setPicture with the modified InputStream. For this you just need to implement the UploadHook interface, since postProcess is not called for ExifUploadHooks. Also beware that setting the InputStream will trigger all UploadHooks again, so it should only be called if your hook actually modified the stream.

    0
  • Zendesk API User
    Author: TimoKalker - 10/19/2023 10:52

    Hi, thanks for the reply!
    Just before sending out the ticket I also got the idea that the (internal) "upload this image" function I expect to be called between the Pre and PostProcess hook takes the reference/instance of how the image file was before I changed it in the preProcess hook - so thanks for confirming my suspicion.

    I also thought about using the postProcess hook, but I struggled finding the resolution (which is only a param in the preProcessHook). I hacked it using 

    Picture.MediaElement.StoreElement#getProject#getOriginalResolution

    but I am not sure if there is ever a case where an Upload is not of Resolution "Original" - and there seems to be no way to get the resolution from the postProcess hook params. Is there a better solution or did I perhaps miss a method that suits my usecase?


    My code works now, but I dont feel good bringing it to prod only having the assumption an upload always has the "original" resolution:

    public void postProcess(@NotNull BaseContext baseContext, @NotNull Media media, @NotNull Picture pictureWithExif, long fileSizeBefore) { baseContext.logDebug("START POST UPLOAD HOOK - PICTURE"); baseContext.logDebug("POST - Media: " + media); baseContext.logDebug("POST - length: " + fileSizeBefore); Resolution originalResolution = pictureWithExif.getProject().getOriginalResolution(); //WARNING: Image might not have been uploaded in the original resolution, this can cause bugs InputStream inputStreamPictureWithExif = null; try { inputStreamPictureWithExif = pictureWithExif.getInputStream(originalResolution); } catch (IOException e) { throw new RuntimeException(e); } ByteArrayOutputStream outputStreamPictureNoExif = new ByteArrayOutputStream(); try { new ExifRewriter().removeExifMetadata(inputStreamPictureWithExif, outputStreamPictureNoExif); // https://commons.apache.org/proper/commons-imaging/apidocs/org/apache/commons/imaging/formats/jpeg/exif/ExifRewriter.html } catch (ImageReadException | ImageWriteException | IOException e) { throw new RuntimeException(e); } int fileSizeAfter = outputStreamPictureNoExif.toByteArray().length; baseContext.logDebug("POST - size-before: " + fileSizeBefore); baseContext.logDebug("POST - size-after: " + fileSizeAfter); if (fileSizeAfter < fileSizeBefore) { baseContext.logInfo("POST UPLOAD HOOK - Picture has exif, replace picture with version of itself without exif"); ByteArrayInputStream inputStreamPictureNoExif = new ByteArrayInputStream(outputStreamPictureNoExif.toByteArray()); try { pictureWithExif.setPicture(originalResolution, fileSizeAfter, inputStreamPictureNoExif, null); } catch (IOException e) { throw new RuntimeException(e); } baseContext.logInfo("POST UPLOAD HOOK - EXIF data got removed from file"); } else { baseContext.logInfo("POST UPLOAD HOOK - Picture has no exif (same file size after removal), no changes required"); } baseContext.logDebug("END POST UPLOAD HOOK"); }





    About the multiple preProcess execution - it would be great to update me once the team finds out what the issue was - I am very curious how this happens.

    0
  • Zendesk API User
    Author: TimoKalker - 10/20/2023 9:32

    and btw, I got it working with "implements ExifUploadHook" - ExifUploadHook is just an Interface without any methods which itself implements UploadHook, it has no functionality, just a more specific name than UploadHook which I preferred over the generic name to show my intent

    0
  • Zendesk API User
    Author: TimoKalker - 10/20/2023 13:09

    Well, I guess I will log whenever an image is uploaded as not-Original and hope that it never happens


    ah, I see, so I guess you had a "UploadHookImpl" and an "ExifUploadHookImpl" that both fired and will discontinue "ExifUploadHookImpl" to fire in future releases.

    I should also combine the postProcess(Picture) and postProcess(File) into one and add a check for the file ending in case some pictures are defined as files (recently with webp as documented in the 2023.10 changelogs), just to be sure to really catch every exif-able file type

    0
  • Zendesk API User
    Author: Windmüller - 10/20/2023 9:56

    Is there a better solution or did I perhaps miss a method that suits my usecase?

    I am sorry but at the moment I do not know of any better way to handle this.

    About the multiple preProcess execution - it would be great to update me once the team finds out what the issue was - I am very curious how this happens.

    That is quite easy. ExitUploadHooks also implement UploadHook and were not excluded from the general "execute all upload hooks" logic.

    ExifUploadHook is just an Interface without any methods which itself implements UploadHook

    That is true but ExifUploadHooks are treated differently. I would still recommend to use a generic UploadHook, since once we fix the issue mentioned above, it is likely that postProcess methods will no longer be called.

    0

Bitte melden Sie sich an, um einen Kommentar zu hinterlassen.