How to convert p:signature value to an image (or o

2019-02-20 10:26发布

问题:

I'm going to use the signature tag of PrimeFaces in my site, but I don't know how can I store in a form of an image in my database or if possible any other type. i just want to display it later in a datatable so the admin can manage and verify the authenticity of those signatures.

this is my xhtml page.

<h:form>
    <p:growl autoUpdate="true" />

    <p:signature style="width:400px;height:200px" widgetVar="sig" value="#{cardBean.card.signature}" required="true" label="Signature" guideline="true"/>

    <div style="margin:20px 0">
        <p:commandButton value="Submit" icon="ui-icon-check" update="output"/>
        <p:commandButton value="Clear" icon="ui-icon-close" type="button" onclick="PF('sig').clear()"/>
    </div>

    <p:outputPanel id="output">
        <h:outputText rendered="#{not empty cardBean.card.signature}" style="font-size:24px;display:block" value="Your Signature" />
        <p:signature style="width:400px;height:200px;" value="#{cardBean.card.signature}" readonly="true"
                     rendered="#{not empty cardBean.card.signature}" backgroundColor="#eaeaea" color="#03a9f4"/>
    </p:outputPanel>

<p:commandButton value="Soumettre"
                        action="#{cardBean.doAjouterSignature()}" update="@all" />
</h:form>

and this is my log

14:12:47,711 INFO  [org.jboss.modules] (main) JBoss Modules version 1.3.3.Final
14:12:48,114 INFO  [org.jboss.msc] (main) JBoss MSC version 1.2.2.Final
14:12:48,180 INFO  [org.jboss.as] (MSC service thread 1-6) JBAS015899: WildFly 8.1.0.Final "Kenny" starting
14:12:51,394 INFO  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) JBAS015003: Found ebankingJSF.war in deployment directory. To trigger deployment create a file called ebankingJSF.war.dodeploy
14:12:51,412 INFO  [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http)
14:12:51,440 INFO  [org.xnio] (MSC service thread 1-7) XNIO version 3.2.2.Final
14:12:51,447 INFO  [org.xnio.nio] (MSC service thread 1-7) XNIO NIO Implementation Version 3.2.2.Final
14:12:51,475 INFO  [org.jboss.as.security] (ServerService Thread Pool -- 45) JBAS013171: Activating Security Subsystem
14:12:51,479 WARN  [org.jboss.as.txn] (ServerService Thread Pool -- 46) JBAS010153: Node identifier property is set to the default value. Please make sure it is unique.
14:12:51,481 INFO  [org.jboss.as.naming] (ServerService Thread Pool -- 40) JBAS011800: Activating Naming Subsystem
14:12:51,485 INFO  [org.jboss.as.security] (MSC service thread 1-12) JBAS013170: Current PicketBox version=4.0.21.Beta1
14:12:51,490 INFO  [org.jboss.as.webservices] (ServerService Thread Pool -- 48) JBAS015537: Activating WebServices Extension
14:12:51,494 INFO  [org.jboss.as.jsf] (ServerService Thread Pool -- 38) JBAS012615: Activated the following JSF Implementations: [main]
14:12:51,495 INFO  [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 32) JBAS010280: Activating Infinispan subsystem.
14:12:51,499 INFO  [org.wildfly.extension.io] (ServerService Thread Pool -- 31) WFLYIO001: Worker 'default' has auto-configured to 16 core threads with 128 task threads based on your 8 available processors
14:12:51,508 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-1) JBAS017502: Undertow 1.0.15.Final starting
14:12:51,509 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) JBAS017502: Undertow 1.0.15.Final starting
14:12:51,521 INFO  [org.jboss.as.connector.logging] (MSC service thread 1-4) JBAS010408: Starting JCA Subsystem (IronJacamar 1.1.5.Final)
14:12:51,548 INFO  [org.jboss.as.naming] (MSC service thread 1-12) JBAS011802: Starting Naming Service
14:12:51,550 INFO  [org.jboss.as.mail.extension] (MSC service thread 1-14) JBAS015400: Bound mail session [java:jboss/mail/Default]
14:12:51,600 INFO  [org.jboss.remoting] (MSC service thread 1-13) JBoss Remoting version 4.0.3.Final
14:12:51,600 INFO  [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 27) JBAS010403: Deploying JDBC-compliant driver class org.h2.Driver (version 1.3)
14:12:51,607 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-9) JBAS010417: Started Driver service with driver-name = h2
14:12:51,619 INFO  [org.jboss.as.connector.subsystems.datasources] (ServerService Thread Pool -- 27) JBAS010404: Deploying non-JDBC-compliant driver class com.mysql.jdbc.Driver (version 5.1)
14:12:51,620 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-1) JBAS010417: Started Driver service with driver-name = mysql
14:12:51,656 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) JBAS017527: Creating file handler for path C:\Users\Ali\Desktop\serveurWildFly\wildfly-8.1.0.Final/welcome-content
14:12:51,670 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-15) JBAS017525: Started server default-server.
14:12:51,686 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017531: Host default-host starting
14:12:51,750 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-1) JBAS010400: Bound data source [java:/ebanking]
14:12:51,752 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-16) JBAS010400: Bound data source [java:/exam]
14:12:51,763 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-9) JBAS017519: Undertow HTTP listener default listening on localhost/127.0.0.1:8383
14:12:51,827 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-12) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS]
14:12:51,911 INFO  [org.jboss.as.server.deployment.scanner] (MSC service thread 1-15) JBAS015012: Started FileSystemDeploymentService for directory C:\Users\Ali\Desktop\serveurWildFly\wildfly-8.1.0.Final\standalone\deployments
14:12:51,913 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) JBAS015876: Starting deployment of "ebankingJSF.war" (runtime-name: "ebankingJSF.war")
14:12:52,136 INFO  [org.jboss.ws.common.management] (MSC service thread 1-9) JBWS022052: Starting JBoss Web Services - Stack CXF Server 4.2.4.Final
14:12:54,556 INFO  [org.jboss.as.jpa] (MSC service thread 1-4) JBAS011401: Read persistence.xml for ebankingEJB
14:12:54,862 INFO  [org.jboss.as.jpa] (ServerService Thread Pool -- 50) JBAS011409: Starting Persistence Unit (phase 1 of 2) Service 'ebankingJSF.war#ebankingEJB'
14:12:54,869 INFO  [org.hibernate.jpa.internal.util.LogHelper] (ServerService Thread Pool -- 50) HHH000204: Processing PersistenceUnitInfo [
    name: ebankingEJB
    ...]
14:12:54,922 INFO  [org.hibernate.Version] (ServerService Thread Pool -- 50) HHH000412: Hibernate Core {4.3.5.Final}
14:12:54,924 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 50) HHH000206: hibernate.properties not found
14:12:54,926 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 50) HHH000021: Bytecode provider name : javassist
14:12:55,045 INFO  [org.jboss.weld.deployer] (MSC service thread 1-3) JBAS016002: Processing weld deployment ebankingJSF.war
14:12:55,180 INFO  [org.hibernate.validator.internal.util.Version] (MSC service thread 1-3) HV000001: Hibernate Validator 5.1.0.Final
14:12:55,237 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named GestionCards in deployment unit deployment "ebankingJSF.war" are as follows:

    java:global/ebankingJSF/GestionCards!services.GestionCardsLocal
    java:app/ebankingJSF/GestionCards!services.GestionCardsLocal
    java:module/GestionCards!services.GestionCardsLocal
    java:global/ebankingJSF/GestionCards
    java:app/ebankingJSF/GestionCards
    java:module/GestionCards

14:12:55,238 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named GestionClient in deployment unit deployment "ebankingJSF.war" are as follows:

    java:global/ebankingJSF/GestionClient!services.GestionClientRemote
    java:app/ebankingJSF/GestionClient!services.GestionClientRemote
    java:module/GestionClient!services.GestionClientRemote
    java:jboss/exported/ebankingJSF/GestionClient!services.GestionClientRemote
    java:global/ebankingJSF/GestionClient!services.GestionClientLocal
    java:app/ebankingJSF/GestionClient!services.GestionClientLocal
    java:module/GestionClient!services.GestionClientLocal

14:12:55,238 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named GestionAccounts in deployment unit deployment "ebankingJSF.war" are as follows:

    java:global/ebankingJSF/GestionAccounts!services.GestionAccountsLocal
    java:app/ebankingJSF/GestionAccounts!services.GestionAccountsLocal
    java:module/GestionAccounts!services.GestionAccountsLocal
    java:global/ebankingJSF/GestionAccounts!services.GestionAccountsRemote
    java:app/ebankingJSF/GestionAccounts!services.GestionAccountsRemote
    java:module/GestionAccounts!services.GestionAccountsRemote
    java:jboss/exported/ebankingJSF/GestionAccounts!services.GestionAccountsRemote

14:12:55,239 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named GestionTransactions in deployment unit deployment "ebankingJSF.war" are as follows:

    java:global/ebankingJSF/GestionTransactions!services.GestionTransactionsLocal
    java:app/ebankingJSF/GestionTransactions!services.GestionTransactionsLocal
    java:module/GestionTransactions!services.GestionTransactionsLocal
    java:global/ebankingJSF/GestionTransactions
    java:app/ebankingJSF/GestionTransactions
    java:module/GestionTransactions

14:12:55,512 INFO  [org.jboss.weld.deployer] (MSC service thread 1-15) JBAS016005: Starting Services for CDI deployment: ebankingJSF.war
14:12:55,537 INFO  [org.jboss.weld.Version] (MSC service thread 1-15) WELD-000900: 2.1.2 (Final)
14:12:55,567 INFO  [org.jboss.weld.deployer] (MSC service thread 1-11) JBAS016008: Starting weld service for deployment ebankingJSF.war
14:12:55,674 INFO  [org.jboss.as.jpa] (ServerService Thread Pool -- 50) JBAS011409: Starting Persistence Unit (phase 2 of 2) Service 'ebankingJSF.war#ebankingEJB'
14:12:55,734 INFO  [org.hibernate.annotations.common.Version] (ServerService Thread Pool -- 50) HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
14:12:56,098 INFO  [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 50) HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
14:12:56,237 INFO  [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (ServerService Thread Pool -- 50) HHH000397: Using ASTQueryTranslatorFactory
14:12:56,534 INFO  [org.hibernate.tool.hbm2ddl.SchemaUpdate] (ServerService Thread Pool -- 50) HHH000228: Running hbm2ddl schema update
14:12:56,534 INFO  [org.hibernate.tool.hbm2ddl.SchemaUpdate] (ServerService Thread Pool -- 50) HHH000102: Fetching database metadata
14:12:56,537 INFO  [org.hibernate.tool.hbm2ddl.SchemaUpdate] (ServerService Thread Pool -- 50) HHH000396: Updating schema
14:12:56,755 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000261: Table found: banque.card_request
14:12:56,755 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000037: Columns: [id, letter, client_id, type, agence, intitule]
14:12:56,755 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000108: Foreign keys: [fk_lcmgyotmshaveq7jopygkpkbr]
14:12:56,755 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000126: Indexes: [primary, fk_lcmgyotmshaveq7jopygkpkbr]
14:12:56,795 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000261: Table found: banque.t_account
14:12:56,795 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000037: Columns: [id, solde, date_creation, min_amount, client_id, type, max_amount, iban]
14:12:56,795 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000108: Foreign keys: [fk_10y3sqkbms3tmyv69xp9qs9nv]
14:12:56,795 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000126: Indexes: [primary, fk_10y3sqkbms3tmyv69xp9qs9nv]
14:12:56,870 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000261: Table found: banque.t_client
14:12:56,871 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000037: Columns: [id, first_name, pwd, last_name, login]
14:12:56,871 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000108: Foreign keys: []
14:12:56,871 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000126: Indexes: [primary]
14:12:56,907 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000261: Table found: banque.t_question
14:12:56,907 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000037: Columns: [produit, id, text, client_id, contact]
14:12:56,907 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000108: Foreign keys: [fk_i7v6miypxgh04j9htf2hiks6k]
14:12:56,907 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000126: Indexes: [primary, fk_i7v6miypxgh04j9htf2hiks6k]
14:12:56,931 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000261: Table found: banque.t_transaction
14:12:56,931 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000037: Columns: [id, date_creation, account_id, status, transaction_type, credit]
14:12:56,931 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000108: Foreign keys: [fk_f9wd4bufpvgj1xr7p8h7vn9h8]
14:12:56,931 INFO  [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 50) HHH000126: Indexes: [fk_f9wd4bufpvgj1xr7p8h7vn9h8, primary]
14:12:56,932 INFO  [org.hibernate.tool.hbm2ddl.SchemaUpdate] (ServerService Thread Pool -- 50) HHH000232: Schema update complete
14:12:57,866 INFO  [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-14) Initializing Mojarra 2.2.6-jbossorg-4 20140501-1134 for context '/ebankingJSF'
14:13:02,980 INFO  [org.primefaces.webapp.PostConstructApplicationEventListener] (MSC service thread 1-14) Running on PrimeFaces 5.2
14:13:02,991 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-14) JBAS017534: Registered web context: /ebankingJSF
14:13:03,030 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "ebankingJSF.war" (runtime-name : "ebankingJSF.war")
14:13:03,129 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9997/management
14:13:03,129 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9997
14:13:03,129 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.1.0.Final "Kenny" started in 16007ms - Started 391 of 444 services (92 services are lazy, passive or on-demand)

回答1:

Just check the PrimeFaces showcase for p:signature. Signature values are bound to a string, so you can simply store a signature as a string in your database. Later you can simply show the signature using the stored string in combination with the readonly attribute set to true. This is exactly what is demonstrated in the showcase.

Your signature string value will look something like:

{"lines":[[[81,75],[81,78],[81,80],[81,84],[83,87],...]]}

If you really want to store it as an image instead of a string, you have a few options.

SVG

As the string basically is an JSON object with a "lines" array, which per line has the coordinates, you can simply transform it to a SVG. All you need to do is create some paths. A rough implementation:

public String toSvg(String signature, int width, int height) {
  List<String> paths = new ArrayList<>();
  try (JsonReader jsonReader = Json.createReader(new StringReader(signature))) {
    JsonObject jsonObject = jsonReader.readObject();
    JsonArray jsonArray = jsonObject.getJsonArray("lines");
    jsonArray.forEach(line -> paths.add(toSvgPath((JsonArray) line)));
  }
  StringBuilder sb = new StringBuilder();
  sb.append(String.format("<svg width=\"%d\" height=\"%d\" xmlns=\"http://www.w3.org/2000/svg\">\n", width, height));
  paths.forEach(path -> sb.append(path));
  sb.append("</svg>");
  return sb.toString();
}


private String toSvgPath(JsonArray line) {
  StringBuilder sb = new StringBuilder("<path d=\"");
  for (int i = 0; i < line.size(); i++) {
    JsonArray coords = (JsonArray) line.getJsonArray(i);
    sb.append(String.format("%s%d %d ", (i == 0 ? "M" : "L"), coords.getInt(0), coords.getInt(1)));
  }
  sb.append("\" stroke=\"black\" fill=\"transparent\"/>\n");
  return sb.toString();
}

But, as the SVG can easily be created from the JSON object, you might just want to store the JSON object and create the SVG when you need to render the signature.

See also:

  • How to convert String to JsonObject
  • Please explain SVG Path Commands and Coordinates

PNG

p:signature has a base64Value attribute which writes a PNG image as base64 encoded data to the provided property:

<p:signature id="signature"
             base64Value="#{myBean.signature}">

This will give you a URL which will look like:

data:image/png;base64,iVBORw0KGgoAAAANSU...

In your bean it's just a matter of getting the data from the URL:

private static final String URL_DATA_PNG_BASE64_PREFIX = "data:image/png;base64,";

..

String encoded = signatureUrl.substring(URL_DATA_PNG_BASE64_PREFIX.length());
byte[] decoded = Base64.getDecoder().decode(encoded);

You could optionally save it as a file:

Path path = Paths.get("path/to/your/image.png");
Files.write(path, decoded);

See also:

  • Decode Base64 data in Java

I would also suggest to download and read the documentation PDF. It also covers an alternative way to get the signature as PNG.



回答2:

I was able to convert the signature into byte array to store it encrypted in my content repository (filenet) using following code:

/**
     * A point along a line within a signature.
     */
    private static class Point {

        private int x;
        private int y;

        public Point(float x, float y) {
            this.x = Math.round(x);
            this.y = Math.round(y);
        }
    }

    public static void generateSignature(String jsonEncoding, OutputStream output) throws IOException {
        output.write(redrawSignature(extractSignature(jsonEncoding)));
        output.close();
    }

    /**
     * Extract the signature lines and points from the JSON encoding.
     * 
     * @param jsonEncoding
     *            the JSON representation of the signature
     * @return the retrieved lines and points
     */
    private static List<List<Point>> extractSignature(String jsonEncoding) {
        List<List<Point>> lines = new ArrayList<List<Point>>();
        Matcher lineMatcher = Pattern.compile("(\\[(?:,?\\[-?[\\d\\.]+,-?[\\d\\.]+\\])+\\])").matcher(jsonEncoding);
        while (lineMatcher.find()) {
            Matcher pointMatcher = Pattern.compile("\\[(-?[\\d\\.]+),(-?[\\d\\.]+)\\]").matcher(lineMatcher.group(1));
            List<Point> line = new ArrayList<Point>();
            lines.add(line);
            while (pointMatcher.find()) {
                line.add(new Point(Float.parseFloat(pointMatcher.group(1)), Float.parseFloat(pointMatcher.group(2))));
            }
        }
        return lines;
    }

    /**
     * Redraw the signature from its lines definition.
     * 
     * @param lines
     *            the individual lines in the signature
     * @return the corresponding signature image
     * @throws IOException
     *             if a problem generating the signature
     */
    private static byte[] redrawSignature(List<List<Point>> lines) throws IOException {
        BufferedImage signature = new BufferedImage(SIGNATURE_WIDTH, SIGNATURE_HEIGHT, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g = (Graphics2D) signature.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, signature.getWidth(), signature.getHeight());
        g.setColor(Color.BLACK);
        g.setStroke(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        Point lastPoint = null;
        for (List<Point> line : lines) {
            for (Point point : line) {
                if (lastPoint != null) {
                    g.drawLine(lastPoint.x, lastPoint.y, point.x, point.y);
                }
                lastPoint = point;
            }
            lastPoint = null;
        }
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(signature, IMAGE_FORMAT, output);
        return output.toByteArray();
    }


回答3:

Value of p:signature store as a string value in database when you decide to send to database as for example {"lines":[[[308.4,113.86],[284.4,117.86],[233.4,125.86],[168.4,135.86],[116.4,143.86],[89.4,145.86],[90.4,145.86],[106.4,141.86],[144.4,135.86],[180.4,131.86],[184.4,131.86],[184.4,131.86],[177.4,131.86]}