File Uploads

From SocialStack
Revision as of 17:10, 17 January 2023 by Luke (talk | contribs)

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 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.