Slim3 Controller‎ > ‎

File Upload

Slim3 supports File Upload.
See MultipartRequestHandler.java and FileUpload.java.

The uploaded result is stored in FileItem.java. So you can get it as follows:
FileItem formFile = requestScope("formFile");

The size of uploaded data is limited to 10MB. See Quotas_and_Limits.
The maximum entity size is 1MB. See Datastore Quotas_and_Limits.
If you want to upload more than 1MB, you should divide the uploaded data as follows:

UploadedData

@Model
public class UploadedData {

    @Attribute(primaryKey = true)
    private Key key;

    @Attribute(version = true)
    private Long version = 0L;

    private String fileName;

    private int length;

    @Attribute(persistent = false)
    private InverseModelListRef<UploadedDataFragment, UploadedData> fragmentListRef =
        new InverseModelListRef<UploadedDataFragment, UploadedData>(
            UploadedDataFragment.class,
            "uploadDataRef",
            this,
            new Sort("index"));
    ...
}

UploadedDataFragment

@Model
public class UploadedDataFragment {

    @Attribute(primaryKey = true)
    private Key key;

    @Attribute(lob = true)
    private byte[] bytes;

    private ModelRef<UploadedData> uploadDataRef =
        new ModelRef<UploadedData>(
            UploadedData.class);

    private int index;

    ...
}

UploadService

public UploadedData upload(FileItem formFile) {
    if (formFile == null) {
        return null;
    }
    List<Object> models = new ArrayList<Object>();
    UploadedData data = new UploadedData();
    models.add(data);
    data.setKey(Datastore.allocateId(d));
    data.setFileName(formFile.getShortFileName());
    data.setLength(formFile.getData().length);
    byte[] bytes = formFile.getData();
    byte[][] bytesArray = ByteUtil.split(bytes, FRAGMENT_SIZE);
    Iterator<Key> keys =
        Datastore.allocateIds(data.getKey(), f, bytesArray.length).iterator();
    for (int i = 0; i < bytesArray.length; i++) {
        byte[] fragmentData = bytesArray[i];
        UploadedDataFragment fragment = new UploadedDataFragment();
        models.add(fragment);
        fragment.setKey(keys.next());
        fragment.setBytes(fragmentData);
        fragment.setIndex(i);
        fragment.getUploadDataRef().setModel(data);
    }
    Transaction tx = Datastore.beginTransaction();
    for (Object model : models) {
        Datastore.put(tx, model);
    }
    tx.commit();
    return data;
}

See demo and source.
The above models use bidirectional one-to-many relationships. If you are not familiar with it, see relationships.

Next...

Continue to Validation.


Comments