Media
Form media
Use the MediaUploader.vue
component to display media and handle uploading temporary media to save to the resource when submitting the (Inertia) form.
Users can drag and drop or click to upload files, with the ability to drag to sort if multiple items are uploaded. An optional cover flag allows marking an item with an icon. Items can be deleted from the list, and each upload undergoes back-end validation. Inline error messages display validation issues, while a toast message appears if the back-end fails. Files are only saved as temporary uploads if they pass validation.
TemporaryFileUploadRules
The front-end file upload rules are shown in the requirements info tooltip in the component. Only the maximum files and accepted MIME types requirements are also used to do some client-side validation, like preventing adding more files than allowed or selecting videos when only images are accepted.
TemporaryFileUploadGroup
Each use of MediaUploader.vue
should be linked to a unique upload group, like category images or a questionnaire cover. This group is used to both figure out which validation rules to use when adding media, and later copying the correct temporary uploads to their final destination.
Each group requires specific back-end file validation rules as a single form request. This form request should be added to \Interfaces\App\Actions\ValidateTemporaryFileUploadGroup
and is used to validate the temporary upload coming from the media component.
Uploading files
The application uses a single file upload endpoint accessible only to authenticated users. Upload requests are rate-limited to 20 per minute for regular users and 200 per minute for other roles. Generic validation ensures all requests require group, UUID, and valid file, with additional validation applied per group. Uploaded files are stored in the database as TemporaryUpload
models within the temporary_uploads
table, each linked to have one Media
model in the default
media collection. The TemporaryUpload
model tracks the upload group and session ID, which is tied to the user, while the Media
model references the original file stored on disk waiting to be attached to the target model when submitting the valid form.
Saving the form
Each valid temporary upload returns the Media
model's UUID, which is added to an array, such as form.images
for a category. The form is saved using only media UUIDs, combining existing media and temporary uploads, as all are stored as Media
records. No revalidation of files or images occurs, only UUID validation using the MediaRules
class. This class applies a batch ModelsExist
rule to verify that each UUID corresponds to either an existing media record or a temporary upload. The validation ensures that temporary upload UUIDs belong to the correct group to prevent cross-group mismatches or confirms that each existing UUID corresponds to an existing media record of the expected model.
Attaching media
When saving, temporary media must be reassigned from the TemporaryUpload
model to the Category
model. This is handled by $category->synchronizeMedia($uuids, $uploadGroup)
, which defines the new media sort order, removes existing media not present in the provided UUID list (sync
), and bypasses certain Spatie Media Library Pro checks. It then moves temporary Media
records by copying and deleting them, and deletes the TemporaryUpload
record since it is no longer linked to any media.
Remark: local/test media
Rearranging existing media right after deploying to a test environment does not work (because of how we statically seed media on test environments and locally). Please delete all media of the resource when editing first. Then upload new media, save, go back to the index, and back to edit to test the edit functionality.