File Pointers / File ID's
Details about working with files in the dexi API
When working with files in results coming from the Dexi platform you'll not receive the entire raw file in the JSON data - but rather receive a so-called Dexi File Pointer. These are small meta-data placeholders Dexi uses to pass files around without passing the entire file around.
You will only receive Dexi file pointers in data-storage
and data-filter
components that allow files to be received in their inputs.
The format is as follows:
FILE:<mimetype>;<size>;<fileId>
Parsing
We might be adding more metadata values to the end of this format so if writing custom parsers you should take care not to have the parser fail if there are more values in the semicolon-seperated list of values.
As an example:
FILE:image/png;432123;BF7656AA-2D88-4248-BD05-AEB5DF9F9670
The file id is the ID of the file that's stored within Dexi and as such is subject to the same TTL rules that other data in Dexi is subject to. What that means is that if the file is part of an execution result it will automatically be deleted after 2-3 weeks.
Storing File Pointers
As a rule of thumb do not store file pointers externally but rather retrieve the data they point to and store that instead.
A simple example of how to do retrieve the contents of a file using the file id
so can be found below.
package my.org.components;
import io.dexi.client.DexiClientFactory;
import io.dexi.client.DexiFileClient;
import io.dexi.service.AppContext;
import io.dexi.service.components.AppComponent;
import io.dexi.service.components.DataStorageAppComponent;
import io.dexi.service.exceptions.UserErrorException;
import io.dexi.service.utils.RowStream;
import my.org.data.MyAppConfig;
import my.org.data.MyComponentConfig;
import my.org.data.SomeRepository;
import java.io.IOException;
@AppComponent("my-app-component")
public class MyAppDataStorageAppComponent implements DataStorageAppComponent<MyAppConfig, MyComponentConfig> {
private final SomeRepository someRepository;
private final DexiClientFactory dexiClientFactory;
public MyAppDataStorageAppComponent(SomeRepository someRepository, DexiClientFactory dexiClientFactory) {
this.someRepository = someRepository;
this.dexiClientFactory = dexiClientFactory;
}
@Override
public Object write(AppContext<MyAppConfig, MyComponentConfig> ctxt, RowStream rows) throws IOException {
//Create a dexi client for the current activation
final DexiClientFactory.DexiClient dexiClient = dexiClientFactory.create(ctxt.getActivationId());
//Imagine we read this from an input value
String stringValue = "FILE:image/png;2344323;CC909360-D324-4FA6-865D-5445C771D0C8";
//Verify the value is a file field (file pointer)
if (DexiFileClient.isFileFieldValue(stringValue)) {
//Get a handle for the file via the API
final DexiFileClient.FileHandle fileHandle = dexiClient.files().getFileFromFieldValue(stringValue);
//Can be null if file was not found
if (fileHandle != null) {
//Do something with the stream on the file handle
someRepository.saveFileFromStream(fileHandle.getStream());
} else {
throw new UserErrorException("File not found");
}
} else {
throw new UserErrorException("File pointer was not valid");
}
return null;
}
@Override
public Class<MyComponentConfig> getComponentConfigClass() {
return MyComponentConfig.class;
}
}
Updated almost 5 years ago