Files

You can use Kinvey to store and retrieve binary files of size up to 5TB. Files can be of any format.

The files are automatically enabled for download using a Content Delivery Network (CDN) for massive scale and performance.

Kinvey does not directly serve or accept files. Instead, the Kinvey Files API works by providing a short-lived URL to a third-party cloud storage service from which file(s) can be uploaded or downloaded. Currently, the third-party service used is Google Cloud Storage.

You would typically use the Files API to upload and download:

  • images
  • video files
  • other application-specific files.

Uploading

The library's File API supports uploading a java.io.File directly as well as streaming content from an InputStream.

java.io.File

To upload a file, use myClient.file().upload(). Pass the file content as the first argument, followed by an UploadProgressListener for callbacks.

When using custom values for _id, you should avoid values that are exactly 12 or 24 symbols in length. Such values are automatically converted to BSON ObjectID and are not stored as strings in the database, which can interfere with querying and other operations.

To ensure that no items with 12 or 24 symbols long _id are stored in the collection, you can create a pre-save hook that either prevents saving such items, or appends an additional symbol (for example, underscore) to the _id:

if (_id.length === 12 || _id.length === 24) {
  _id += "_";
}

import com.kinvey.java.core.UploadProgressListener;

...
try{
    java.io.File file = new java.io.File(getFilesDir(), "chicken_fried_waffles.txt");
    file.createNewFile();

    myClient.file().uploadBlocking(file, new UploaderProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("upload success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("upload progress change!");
        }

        @Override
        public void progressChanged(MediaHttpUploader uploader) throws IOException {
            System.out.println("upload progress change -> " + uploader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't upload! -> " + e);
    e.printStackTrace();
}

Optionally, you can use a FileMetaData object as the first parameter to save additional metadata. This lets you set ACLs, mark files as public, and set any other custom attributes your app may need.

import com.kinvey.java.model.FileMetaData;
import com.kinvey.java.model.KinveyMetaData.AccessControlList;
...

FileMetaData metadata = new FileMetaData("myFileID");  //create the FileMetaData object
metadata.setPublic(true);  //set the file to be pubicly accesible
metadata.setAcl(new KinveyMetaData.AccessControlList().setGloballyReadable(true)); //allow all users to see this file
metadata.setFileName("chicken_fried_waffles.txt");

try{
    java.io.File file = new java.io.File(getFilesDir(), "chicken_fried_waffles.txt");
    file.createNewFile();

    myClient.file().uploadBlocking(metadata, file, new UploaderProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("upload success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("upload progress change!");
        }

        @Override
        public void progressChanged(MediaHttpUploader uploader) throws IOException {
            System.out.println("upload progress change -> " + uploader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't upload! -> " + e);
    e.printStackTrace();
}

InputStream

Alternatively you can upload a file from an input stream.

try{
    FileInputStream fIn = new FileInputStream(new File ("eats_bacon.mpg"));
    myClient.file().uploadBlocking("myFileID", fIn, new UploaderProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("upload success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("upload progress change!");
        }

        @Override
        public void progressChanged(MediaHttpUploader uploader) throws IOException {
            System.out.println("upload progress change -> " + uploader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't upload! -> " + e);
    e.printStackTrace();
}

You can also provide a FileMetaData object as the first argument when streaming from an InputStream.

import com.kinvey.java.model.FileMetaData;
import com.kinvey.java.model.KinveyMetaData.AccessControlList;
...

FileMetaData metadata = new FileMetaData("myFileID");  //create the FileMetaData object
metadata.setPublic(true);  //set the file to be pubicly accesible
metadata.setAcl(new KinveyMetaData.AccessControlList().setGloballyReadable(true)); //allow all users to see this file
metadata.setFileName("eats_bacon.mpg");

try{
    FileInputStream fIn = new FileInputStream(new File ("eats_bacon.mpg"));
    myClient.file().uploadBlocking(metadata, fIn, new UploaderProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("upload success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("upload progress change!");
        }

        @Override
        public void progressChanged(MediaHttpUploader uploader) throws IOException {
            System.out.println("upload progress change -> " + uploader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't upload! -> " + e);
    e.printStackTrace();
}

Uploading publicly readable files

Use the method myFileMetaData.setPublic(true) if you want to upload a publicly-readable file. This means that the download link to the file will not expire until you delete the file through Kinvey.

import com.kinvey.java.model.FileMetaData;
...

FileMetaData myFileMetaData = new FileMetaData("myFileID");  //create the FileMetaData object
myFileMetaData.setPublic(true);  //set the file to be pubicly accesible
metadata.setFileName("chicken_fried_waffles.txt");

try{
    java.io.File file = new java.io.File(getFilesDir(), "chicken_fried_waffles.txt");
    file.createNewFile();
    myClient.file().uploadBlocking(myFileMetaData, file, new UploaderProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("upload success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("upload progress change!");
        }

        @Override
        public void progressChanged(MediaHttpUploader uploader) throws IOException {
            System.out.println("upload progress change -> " + uploader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't upload! -> " + e);
    e.printStackTrace();
}

Downloading

For downloading files to an OutputStream, you can open a file output stream, by name, then feed the file output stream to the file download.

FileOutputStream fos= new FileOutputStream("mug.png");
try{
    myClient.file().downloadBlocking("myFileID", fos, new DownloadProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("download success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("download progress change!");
        }

        @Override
        public void progressChanged(MediaHttpDownloader downloader) throws IOException {
            System.out.println("download progress change -> " + downloader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't download! -> " + e);
    e.printStackTrace();
}

Specifying a custom expiration time

Files can also be retrieved by a query, and you can optionally set a custom expiration time (in seconds) if you need the temporary URL to last longer (or shorter) than one hour.


import com.kinvey.java.Query;

...

FileOutputStream fos= new FileOutputStream("mug.png");
Query q = new Query() //create a new query
q.equals("ttl_in_seconds", 3600);  //set a new ttl for the download URL
try{
    myClient.file().downloadBlocking("myFileID", q, fos, new DownloadProgressListener() {
        @Override
        public void onSuccess(Void result) {
            System.out.println("download success!");
        }

        @Override
        public void onFailure(Throwable error) {
            System.out.println("download progress change!");
        }

        @Override
        public void progressChanged(MediaHttpDownloader downloader) throws IOException {
            System.out.println("download progress change -> " + downloader.getUploadState());
        }

    });
}catch(IOException e){
    System.out.println("Couldn't download! -> " + e);
    e.printStackTrace();
}

Deleting

You can permanently remove a file using the delete() method, which takes the unique file _id.

try{
    KinveyDeleteResponse delete = myJavaClient.file().deleteBlocking("myFileID").execute();
}catch(IOException e){
    System.out.println("Couldn't delete! -> " + e);
    e.printStackTrace();
}

Deletion can also be performed by providing a FileMetaData object which must contain an _id.

try{
    KinveyDeleteResponse delete = myJavaClient.file().deleteBlocking(new FileMetaData("myFileId")).execute();
}catch(IOException e){
    System.out.println("Couldn't delete! -> " + e);
    e.printStackTrace();
}

Unlike the other APIs accesible through the Client, for File requests you do not have to call execute() (except for delete()), however you must pass an UploadProgressListener or DownloadProgressListener as the final arguement.