Studio 6.10.2 Support for Media Upload

I’m brand new to CUBA Platform and Studio so usual apologies and disclaimers apply :slight_smile:

I’m tring to create an edit screen for an entity that has an image column. Standard HTML has the input type file with “accept” and “capture” attributes that should allow me to load the image into the entity from a web cam. Studio has the file upload component which includes the “accept” attribute which appears not to work - no matter what value I specify, the HTML generated always contains the same “application/octet” string :frowning: . “capture” is not provided in Studio at all as far as I can see.

So given that Studio 7 is now available is Studio 6.10 still supported? If so can “accept” be fixed if it is broken and what are the chances of supporting “capture”. I have tried to add a new component by using the slider sample but even following the documentation to the letter the slider doesn’t work as when I launch the web page it complains that it cannot find the javascript init method even though I’ve created it as per the guide :frowning: :frowning:

Thanks for any pointers/comments.
Andrew Waters UK.

Hi,

According to the documentation:

The accept XML attribute (and the corresponding setAccept() method) can be used to set the file type mask in the file selection dialog. Users still be able to change the mask to “All files” and upload arbitrary files.
The value of the attribute should be a comma-separated list of masks. For example: *.jpg,*.png.

So, in order to capture image from a webcam, you need to implement some JavaScript component.

I suppose that you have some errors in your javascript connector file. Please check browser console.

As an example, I’ve integrated a simple WebcamJS in order to take snapshots.

First of all, I downloaded webcam.js from the project github repository.
Then implemented a server side component and a JavaScript connector:

package com.company.demo.web.toolkit.ui.webcam;

import com.haulmont.cuba.web.sys.WebJarResource;
import com.vaadin.annotations.JavaScript;
import com.vaadin.ui.AbstractJavaScriptComponent;
import elemental.json.JsonValue;

import java.util.function.Consumer;

@WebJarResource({"jquery:jquery.min.js"})
@JavaScript({"webcam.js", "webcam-connector.js"})
public class WebCamCapture extends AbstractJavaScriptComponent {

    private Consumer<String> listener;

    public WebCamCapture() {
        addFunction("onSnapshot", arguments -> {
            JsonValue value = arguments.get(0);

            listener.accept(value.asString());
        });
    }

    public void takeSnapshot() {
        callFunction("takeSnapshot");
    }

    public void setListener(Consumer<String> listener) {
        this.listener = listener;
    }
}
com_company_demo_web_toolkit_ui_webcam_WebCamCapture = function() {
    var connector = this;
    var element = connector.getElement();
    $(element).html('<div id="my_camera" style="width:320px; height:240px;"></div>');
    Webcam.attach('#my_camera');

    connector.takeSnapshot = function() {
        Webcam.snap( function(data_uri) {
            connector.onSnapshot(data_uri);
        });
    }
}

Using WebcamJS we can obtain Base64 string that represents an image. As an example, I decode that string and use it as source for the Image component:

<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
        class="com.company.demo.web.screen.NewScreen"
        messagesPack="com.company.demo.web.screen"
        caption="msg://caption">
    <layout>
        <vbox spacing="true">
            <vbox id="webCamBox"
                  spacing="true"
                  width="AUTO">
                <button id="btn"
                        caption="Take Snapshot"
                        invoke="takeSnapshot"/>
            </vbox>

            <image id="image" width="AUTO"/>
        </vbox>
    </layout>
</window>
package com.company.demo.web.screen;

import com.company.demo.web.toolkit.ui.webcam.WebCamCapture;
import com.haulmont.cuba.gui.components.AbstractWindow;
import com.haulmont.cuba.gui.components.Image;
import com.haulmont.cuba.gui.components.StreamResource;
import com.haulmont.cuba.gui.components.VBoxLayout;
import com.vaadin.ui.AbstractOrderedLayout;

import javax.inject.Inject;
import java.io.ByteArrayInputStream;
import java.util.Base64;
import java.util.Map;

public class NewScreen extends AbstractWindow {
    @Inject
    private VBoxLayout webCamBox;
    @Inject
    private Image image;

    private WebCamCapture webCamCapture;

    @Override
    public void init(Map<String, Object> params) {
        webCamCapture = new WebCamCapture();
        webCamCapture.setListener(value -> {
            // Convert Base64 string to a byte array that can be used as an image resource
            byte[] decodedValue = Base64.getDecoder().decode(value.replace("data:image/jpeg;base64,", ""));
            
            image.setSource(StreamResource.class).setStreamSupplier(() ->
                    new ByteArrayInputStream(decodedValue));
        });

        webCamBox.unwrap(AbstractOrderedLayout.class).addComponent(webCamCapture, 0);
    }

    public void takeSnapshot() {
        webCamCapture.takeSnapshot();
    }
}

File structure:
image

And the result:

image

Full demo project: webcam-capture-demo.zip (92.1 KB)

4 Likes

Wow!
First I tell myself off for not reading the docs about “accept” and making incorrect assumptions about what it was intended for :frowning:

Second WOW WOW for taking the time to show me how to solve my problem in such detail even providing the solution! I’ve been out of the country so I’ll try your solution and investigate what the problem was with my test as soon as I can.

Thank you somuch.
Andrew.

I should have responded sooner just to confirm that this solution worked like a charm.

Thank you again.

1 Like