File Uploads

From SocialStack
Revision as of 10:04, 26 May 2023 by Ablewhite (talk | contribs) (Added section detailing `file-consistency` API)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

SocialStack has a mechanism for uploading public or private files. When a file is uploaded, the upload endpoint will return a file ref for the new file, which is then typically the main way to refer to a particular file.

By default, when uploading an image file, it will automatically be resized into a collection of different sizes for convenience. This works on modern image formats like webp too.

If you need video to be handled as well, you can either install the Api/FFmpeg module and ffmpeg on the target servers (ffmpeg is installed by default on all SocialStack cloud servers), or perform remote transcoding with huddle servers. Transcoding video is a very heavy process but usually mandatory if a CDN is involved in your project due to the file size limits of a CDN, and also end users benefit by being able to skip through the video substantially faster.

Displaying a file uploader

Use type="file" for a file uploader. When the form is submitted, the value will be the file ref:

import Input from 'UI/Input';

...

<Input type="file" name="myFile" label="My File Uploader" />

This defaults to storing files in the public file store. If you want them to be private, add the isPrivate prop:

import Input from 'UI/Input';

...

<Input type="file" name="myFile" label="My File Uploader" isPrivate />

Making use of an uploaded file

On the frontend

An uploaded file is represented as a file ref on the frontend - see the file ref wiki article on how to work with those on the frontend.

In the API

As an upload is a content type, you can subscribe to Upload related events to handle when a new file is uploaded. This is often not the easiest to work with though; more on that in a moment:

Events.Upload.AfterCreate.AddEventListener(async (Context context, Upload upload) => {
    
    if(upload == null) {
        return upload;
    }
    
    // Do something with upload here.
    
    return upload;

});

// AfterUpdate, AfterDelete etc

However, because this event runs whenever any file is uploaded, there's no context on why it was uploaded. This is fine if you're building something like a transcoder which just cares about file type, but not if you're making something that requires a specific file. Instead, it's recommended to make a custom endpoint which receives a ref for that situation.

For example, the frontend may have a form like this:

<Form action="attendee/from-csv" submitLabel="Apply">
    <Input type="file" label="Attendee CSV" name="csvRef" isPrivate/>
</Form>

When the file is uploaded and the form is submitted, a JSON payload containing a field called csvRef will get posted to the endpoint, and the payload would look something like this:

{
    "csvRef": "private:42.csv?s=..."
}

From there, a C# asp.net controller method can capture the ref value:

[HttpPost("from-csv")]
public async ValueTask FromCsv([FromBody] CsvRefPayload payload)
{
    var context = await Request.GetContext();
    var csvRef = payload.csvRef; // the string

    // Do something fun with the csvRef here! (there's more on handling refs in the API in the file ref wiki).
}

...

public class CsvRefPayload
{
    public string csvRef;
}

For information on using a ref in the API, see the file ref wiki page.

Upload metadata

On the frontend

File uploads are a content type (called Upload), meaning all the usual conveniences apply: you can list all uploads, use Loop on them and so on - provided the user has permission to do so.

<Loop over='upload'>{anUpload => <>{anUpload.originalName}</>}</Loop>

// Or if you want an array of uploads:

webRequest('upload/list').then(response => {
    // response.json.results
})

In the API

As with other content types, either use injection or Services.Get to access the UploadService. From there, you can List/ Update and so on the upload you're interested in.

File Consistency

When uploading images, SocialStack automatically produces resized versions of each image (along with optionally converting to WEBP format), dependent on the uploader configuration. It is possible however that if configuration settings are subsequently changed, any new image sizes / formats will be unavailable for existing uploads.

To address this, SocialStack provides an API endpoint (/v1/upload/file-consistency) which can be called to ensure all requested image sizes / formats are available for all image uploads. Please note, the use of a local GPU is highly recommended, as this process can take a substantial amount of time. Progress can be viewed via messages logged to the SocialStack API window.

Updating a specific range of images

Use /v1/upload/file-consistency?idRange=[from_id]-[to_id] (e.g. /v1/upload/file-consistency?idRange=1000-1042) to restrict consistency checks for uploads only within the given ID range.

Forcing image regeneration

By default, SocialStack will leave existing images untouched, simply creating new image sizes / formats only when missing. To force the regeneration of images regardless of whether or not they already exist, use /v1/upload/file-consistency?regenBefore=[iso_date] (use new Date().toISOString() to generate a current ISO date).

This will ensure image sizes / formats are recreated, as long as they're dated before the ISO date specified.