The art of uploading to not yet existing entities in RESTful applications

rest

Single page appliations are the preferred way to build appealing web apps these days. If those apps are not already playing with GraphQL, most of them still rely on a more or less RESTful API to interact with the backend. In most cases, it is not an issue to create a new REST entity with a single call to the backend, as a JSON can include all necessary Data. But when it comes to files which are attached to an entity, things will become a little cumbersome.

Imagine the following situation: You are creating a your brand new JIRA clone. It should be a SPA wich uses your favourite backend language and framework, as well as a relational database. You are currently creating a “Create Issue” form.

Similar to JIRA, you want to attach pictures and other files to the issue you are currently creating. As you are working with a relational database, you want to have a relation between your issues and the uploaded files to quickly query all files that are attached to an issue. This is where you start running into problems. You cannot upload the file instantly after the user selects it in the browser, because there is no “Issue” entity in the backend yet, to which you could attach the uploaded file. The related “Issue” entity will be created if the user hits the “Create” button. So, how to solve this problem? I tried to collect the possible solutions and ordered them from “Bad” to “Still not beautiful, but a good trade-off for me”.

Your files during upload

Your files during upload

1. Adding base64 encoded file to JSON

On submission of your form, you would encode your file content in base64 and attach it to a field of your submitted JSON. You’d have to provide an according deserialization method in the backend to convert the base64 string back into a file object. I wouldn’t recommend this solution as base64 encoding may be errorprone due to different implementations on the frontend and backend. Additionally, base64 encoded files are approximately 37 % bigger than the original filesize. That said, the JSON will be sent and the actual upload will be performed once the user hits the “Create” button. The upside of all of this is, that you can work with JSON instead of plain old FormData (yay!). In the backend you will have all necessary data in place with a single call to create the appropriate database relations.

Your JSON would look something like this:

{
    "summary": "This will include a file!",
    "description": "Indeed, it does!",
    "files": [
        "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gODUK/9sAQwAFAwQEBAMFBAQEBQUFBgcMCAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERghGBodHR8fHxMXIiQiHiQcHh8e/9sAQwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e/8AAEQgCQQJBAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+y6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUlLRQAUUUUAFFFFABRRRQAUUUUAJRRmigBaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACigUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAlFFFAC0lLRQAUlFLQAUlLSUAFFFFABRRRQAUUVT1rVdM0XTZtT1i/tdPsoF3S3FxKI40HuxOKALlGcV8p/Fv9snw7pDTad8PdKOu3S5X7fd7orVT6qvDyf8Ajg9Ca+V/iJ8aviZ48kkXX/FV79kf/lytW8i3A9NiYDfVsn3oA/SDxV8V/ht4Xdo9d8baJaTJ96H7Uryj/gCZb9K4e8/ao+CVs+0eKpp8HrFp05H/AKAK/NQ8nJooA/SQftY/BPP/ACMN9/4LJ/8A4mtCy/ad+CV0QP8AhM1gJ/57WNwv/slfmXRQB+rWkfGf4UaqQtn8QfDpY9BLerEfyciuy0zVNM1SLztN1GzvYzzvt5lkH5qTX451Ysb29sJ1nsbu4tZVOVeGQowPsRQB+yFJX5e+CP2hvi74Tlj+x+MLzULdOttqZ+1RsPTL5YD/AHWFfUHwd/bC8MeIJodL8e2C+HL58KL2Ji9m598/NF+O4erCgD6ioqKyura9tIruzuIri3mUPHLE4ZHU9CCOCKloAKKKKACiiigAooooAKWkooAKKKKAFopKKAClpKKAClpKKACiiigAoopaAEooooAWkoooAKKKKAFopKWgAooooAKKKKACkpaKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopKWgAooo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ds5xXu9ABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAHOePvA3hPx5o7aV4r0S11O352GRcSRH1Rx8yn3BFfI/xW/Yv1S2llvvhxrcd7AcsNO1JhHKvskoG1v8AgQX6mvtuigD8qdU+CPxd02+NncfDrxI8gON1tYvPH/33GGX9a9y/Zn/Za8SSeKLLxT8SLBdM02ykWeDTZWVprl1OV3gEhEB5IPJxjAHNfclFABxRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABSUtJQAtFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFJS0UAIaWiigBKWiigApKWigBDS0UUAJRS0UAJRS0UAJRS0UAJS0UUAJRS0UAFFFFACUtFFACUUtFABRRRQAUUUUAFFFFACUtFFACUUtFACUtFFACUtFFACUtFFABRRRQAUUUlABS0lFAC0lLSUALSUUtABRSUUAL+NFFFABRRRQAUUUUAFFFFABRRSUALRSUtABRRRQAUUUUAFFJS0AFFFJQAtFFH4UAFFFFABRRRQAUUUUAFFFJQAtFFFABRRQKACiiigAooooAKKSloAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooASlpKKAFopKKACiiigBaKSigApaSigBaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiikoAWikpaACiiigApKWigAooooAKKKO1ABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABSUtFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFJRRQAtFFFABRSUUAFFFFAC0UUUAHag0UUAFFFFABRRRQAUUUUAFFFFABRRRQAd6BRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFBoooAKKKKACg0UUAFFFFABRRRQAUUUUABooooAKDRRQAUUUUAFFFFAB3ooooAKPWiigAooooAO1FFFABRRRQAUGiigAooooAKKKKACiiigAo70UUABooooAKKKKACiiigD/9k="
    ]
}

Additionally, this kind of JSON might be a little difficult to read for humans.

This is actually the solution JIRA provides for this problem. Their REST API uses two separate calls for “POST Issue” and “POST Attachment to Issue”. This approach might lead to missing attachemnts after the user submitted his data. The first call might go through the wire, which will return the ID for the newly created Issue, that will be used by the “Upload” call to identfy the upload target. For whatever reason (network instability?), this second call could fail and lead to the situation that the Issue got created successfully, but the attachment is missing. Sure, there are ways to work around this limitation by providing appropriate errormessages, but it would be better to avoid the problem entirely.

3. Send plain old FormData

Okay, lets take two steps back. Why don’t we just use the web the way it was originally designed to be used? Do you really need to send JSON to your HTTP endpoint? Do you really need to send JSON lists and nested objects? If the answer is “No”, then you could go ahead and send plain old FormData. FormData endpoints can be described by Swagger (Open API) and other documentation frameworks, so this area would still be covered. If you insist on using JSON, you could serialize it to a form field and send it as string in a form property to the server together with your attachments. This will cause some deserialization effort on the server side. The biggest downside to this would be, that API documentation will become messy, especially if the documentation is generated automatically from code.

The downside of all previously mentioned proposals

All of the mentioned solutions share one flaw: The attachment upload will start once the user created the depending Issue in the database. If the filesize is considerable and the user is working with a poor network connection, usability might suffer due to delays after issue creation and during the upload. We shouldnt bother our users with more waiting time than absolutely necessary.

4. Create an entity stub on page load

This approach would be applicable, if you are creating a “Draft” feature, that creates a new issue in the database as soon as the user opens the “Create” dialog. Such a feature might come handy to retain form data if the user refreshes the page or logs in from another client. There would be an “Issue” record in the databse from the start, which would provide the foreign key for new upload records already when the creation process is not yet finished. Though this might sound like a clean and good solution, it may cause significant effort to implement this in a clean manner.

5. Upload files without relation to entity, add relation during creation of the entitiy

This solution requires some database cleanup from time to time, but apart from that, it needs only little effort to be implemented. This is the deal: If the user adds a file to be uploaded during the issue creation process, it will be instantly uploaded to the server, without any realtion to an issue. During this process, the user keeps on working on his new issue. After the upload finished, the ID of the uploaded file will be returned to the client and the client will include this Upload ID during submission of the issue to create the actual references.

That solution requires a specific database design, as a database enforced 1:n relation cannot be used, because this would not allow to upload attachments without a foreign key. You either handle the relation on the application level (not database enforced) or you create a n:n relation between issues and files, though you need only a 1:n relation.

You still need to find a solution for the cases, when the user uploads files during the issue creation, but decides then not to finish the creation or refreshes the page. You need to find a way to clean the orphaned database entries, which will not be used anymore by a soon-to-be-created issue.

One “simple” way to achieve this would be to add a “dateCreated” column to your upload records and trigger a CRON job, which deletes all orphaned uploads older than x days.

Your CRON Job, cleaning up the database

Your CRON Job, cleaning up the database

Another, more sophisticated, solution would be to create a websocket connection once the user opens the “Create” dialog, which will check if the user is still creating the issue. If the connection gets closed before the user finished the creation of his issue, all previously added attachments will be removed from the database.

Feel free to leave a comment or add an approach, which I did not come up with.

About me

image
Klaus Deja
Passionate coder. Working in IT since 2008, developer since 2015. I'm living in Duisburg, Germany. Creating JIRA plugins for a living at ease solutions. Always curious about new technologies.