0

管理者ユーザーが画像を Play にアップロードできるようにする POST サービスを作成しています。アプリケーションをテストしていますが、組み込みの H2 ファイルシステム データベースを使用しています。によると

https://gist.github.com/1256286#file-picture-java-L3

これらの画像を Play に保存する良い方法です! はバイト配列であり、 を使用してレンダリングされますController#renderBinary(...)

この関数のCampaignオブジェクトは、キャンペーンに関するすべてのデータを格納し、Bannerオブジェクトのリストを持ちます。各オブジェクトは基本的に画像ファイルといくつかのメタデータです。カスタムの下の次のメソッドControllerは、アップロード用の画像を受け取ることになっています。

public static void putCampaignBanner (Upload bannerFile) {
    Campaign campaign = findCampaignByIdOrNew();

    if(campaign.banners == null) {
        campaign.banners = new LinkedList<Banner>();
    }

    String name = params.get("name", String.class);
    int width = 0;
    int height = 0;
    try {
        BufferedImage image = ImageIO.read(bannerFile.asFile());
        width = image.getWidth();
        height = image.getHeight();
    } catch (IOException e) {
        //it's not a picture.  die gracefully.
        e.printStackTrace();
        renderJSON(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(campaign));
        return;
    }
    if(name==null||name.length()==0) {
        //no name.  die gracefully.  like a swan.
        renderJSON(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(campaign));
        return;
    }

    Banner banner=null;

    for(Banner b: campaign.banners) {
        if(b.name.equals(name)) {
            banner = b;
            break;
        }
    }
    if(banner==null) {
        banner=new Banner();
        banner.name=name;
        banner.campaign = campaign;
        banner.save();
        campaign.banners.add(banner);
    }

    //validate file and populate banner

    //__ vv THIS LINE CAUSES THE EXCEPTION__
    banner.file = bannerFile.asBytes();
    //__ ^^ REMOVING THIS LINE PREVENTS THE EXCEPTION__

    banner.contenttype = bannerFile.getContentType();
    banner.width = width;
    banner.height = height;
    banner.url = getRouterUrlWithId("ImageService.getById", banner.id);

    //__ vv THIS LINE THROWS THE EXCEPTION__
    campaign.save();
    banner.save();

    renderJSON(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(campaign));

}

別の開発者がアップロード フォームを完了するのを待っているので、curl を使用してこれをテストしています。

curl http://[ourserver]:9000/TemplatePopulationController/putCampaignBanner -i -F campaignPrimaryId=44 -F name=headerBanner -F bannerFile=@tempimages/pissybiscuit.png

明らかに、画像を保存する必要があります。PersistenceException を防ぐにはどうすればよいですか?

更新 @Lob アノテーションをに追加しbyte[]、引数の型を変更しBlobてオブジェクトを永続化しようとしました。どちらも機能していません。

ログを調べると、サーバーで次のような GenericJDBCException が発生したことがわかりました。

Caused by: org.h2.jdbc.JdbcBatchUpdateException: Hexadecimal string with odd number of characters: "c73e69c8-3443-489a-b5f0-ef40af99673f|image/jpeg";

エラーのインスタンスのログは次のとおりです。

@6d0npdn4l
Internal Server Error (500) for request POST /TemplatePopulationController/putCampaignBanner

Execution exception (In /app/controllers/TemplatePopulationController.java around line 285)
PersistenceException occured : update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=?

play.exceptions.JavaExecutionException: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=?
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:229)
    at Invocation.HTTP Request(Play!)
Caused by: javax.persistence.PersistenceException: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=?
    at play.db.jpa.JPABase._save(JPABase.java:50)
    at play.db.jpa.GenericModel.save(GenericModel.java:184)
    at controllers.TemplatePopulationController.putCampaignBanner(TemplatePopulationController.java:285)
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
    ... 1 more
16:06:36,553 INFO  ~ campaignPrimaryId=8
16:06:36,571 WARN  ~ SQL Error: 90003, SQLState: 90003
16:06:36,571 ERROR ~ Hexadecimal string with odd number of characters: "363438fc-f232-401e-9f69-7db499a24ba4|application/octet-stream"; SQL statement: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=? [90003-170]
16:06:36,572 WARN  ~ SQL Error: 90003, SQLState: 90003
16:06:36,572 ERROR ~ Hexadecimal string with odd number of characters: "363438fc-f232-401e-9f69-7db499a24ba4|application/octet-stream"; SQL statement: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=? [90003-170]
16:06:36,572 ERROR ~ Could not synchronize database state with session org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException (SQLStateConverter.java:140)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:345)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
    at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:795)
    at play.db.jpa.JPABase._save(JPABase.java:47)
    at play.db.jpa.GenericModel.save(GenericModel.java:184)
    at controllers.TemplatePopulationController.putCampaignBanner(TemplatePopulationController.java:285)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
    at play.server.PlayHandler$NettyInvocation.execute(PlayHandler.java:220)
    at play.Invoker$Invocation.run(Invoker.java:265)
    at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:200)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.h2.jdbc.JdbcBatchUpdateException: Hexadecimal string with odd number of characters: "363438fc-f232-401e-9f69-7db499a24ba4|application/octet-stream"; SQL statement: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=? [90003-170]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1121)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 29 more
16:06:36,591 ERROR ~

@6d0npdn4m
Internal Server Error (500) for request POST /TemplatePopulationController/putCampaignBanner

Execution exception (In /app/controllers/TemplatePopulationController.java around line 285)
PersistenceException occured : update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=?

play.exceptions.JavaExecutionException: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=?
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:229)
    at Invocation.HTTP Request(Play!)
Caused by: javax.persistence.PersistenceException: update Banner set campaign_id=?, file=?, height=?, name=?, url=?, width=? where id=?
    at play.db.jpa.JPABase._save(JPABase.java:50)
    at play.db.jpa.GenericModel.save(GenericModel.java:184)
    at controllers.TemplatePopulationController.putCampaignBanner(TemplatePopulationController.java:285)
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
    ... 1 more
4

1 に答える 1

1

これは、Play と H2 の間の相互作用の問題が原因でした。回答の一部については、この記事にお世話になっています。

http://www.lunatech-research.fr/playframework-file-upload-blob

プレイだそうです!オブジェクトを Binary Large OBject としてデータベースに実際に配置するのではなくBlob、"attachments" というフォルダー (パスは構成可能) にファイルとして格納します。このフォルダー内のファイルはすべてファイル名として UUID を持ってい.pngます。何プレイ!データベースに格納されるのは、ファイル名とコンテンツ タイプです。

c73e69c8-3443-489a-b5f0-ef40af99673f|image/jpeg

ただし、これc73e69c8-3443-489a-b5f0-ef40af99673fは 16 進数ではなくファイル名です。H2 はそれが 16 進数であると想定し変換しようとしているか、Play! として格納されている 16 進数を期待するように H2 を呼び出している可能性がありますString。いずれにせよ、プレイ!は実際にBlobは SQL BLOB として格納されておらず、String代わりに格納しようとしている は 16 進値として解釈されています。

Caused by: org.h2.jdbc.JdbcBatchUpdateException: Hexadecimal string with odd number of characters: "c73e69c8-3443-489a-b5f0-ef40af99673f|image/jpeg";

プレイの切り替え!データベースをMySQLデータベース(とにかくテスト後に計画されていた)に接続すると、機能しました。H2 または Play を実際に書き換えずにH2 を使用している間にこれを修正できるかどうかはわかりませんが、誰かが修正を知っている場合は、それを答えとしてマークします。

于 2013-01-07T15:57:31.517 に答える