I want to create a server side API that has two parameters:
A signature (using the signature pad component from the marketplace)
An objectId
Then using cloud code I want to save the signature and use the file URL and add it to a relevant entry in the database using the ObjectID.
I tried creating a service with params “signature” with type “any object”. Unfortunately this does not let me use the param as input for “file content”.
What’s the correct way of achieving this goal?
Additional context - the reason I want to do this on the server side is because I want to
a) implement business logic to verify if the user is allowed to add a signature
b) ensure the signature file naming cannot be changed by the user, and
c) prevent the possibility for users to associate any other signature file to be added to the database.
If there’s a better way to achieve the above, feel free to suggest.
An API service running in Backendless can accept requests only with the application/json Content-Type for POST and PUT requests. If you need to send a file, you’d need to encode the file contents in request body. You can encode the signature to base64 and send it as a string argument to the API service.
An alternative approach could be using the File Upload API and then add an event handler (before or after) in the Cloud Code to add some additional processing and logic.
Hi Stanislaw, thanks for this. I actually have tried what you said and I think I managed to have this sent successfully. However, I am not successful in recomposing the file back to a PNG that I can open.
Below is what I did, I wonder if someone can point me to where I went wrong.
For every single API in Backendless you can inject your own logic that will be executed either right before Backendless does its job with the API or right after (or both if you will). To create an event handler, navigate to Cloud Code > Event Handlers and click New Event Handler:
It will create an after handle for the Upload API call. What this means is every time you upload a file, the logic of the handler will run and you can do anything you need in there. Btw, notice the Context drop-down, here you can specify for which root-level directories the handler would apply.
With this solution, you can use the standard File Upload API and then execute any additional logic (in the handler which runs in the Cloud Code).
I see. Super useful to know for the future. Though I think the original approach I am going for is more suitable for me since I will also use file upload for other purposes in the future.
So if anyone can assist with my original query, that would be most appreciated.
Why do you think the solution with the event handler is less suitable? I believe it is easier to implement and removes any necessity to do content encoding/decoding.
I “thought” if later I want to allow user to upload different things, such as profile pictures etc, then I would have to add more logic to the event handler. So 1 API service would be handling multiple business logics. And in addition I foresee the permission to upload will be dependent on what the user is doing.
This is why I “assumed” using events on the standard service is a sub-optimal way.
Have I mistaken it here? I have no idea what the best practices should be, so any suggestions welcomed.
If different file types require different processing, then the logic must change somewhere. Whether it is your API service or an event handler, there would still be some work. With event handlers, you can differentiate by having different afterUpload handlers assigned to different folder. For instance, you can configure your app to upload images to /imageUploads and have one event handler for that folder while PDFs go to /pdfUploads and have another handler for that folder.
In the meantime I figured out why my original solution didn’t work.
For others facing the same issue, the “read file as” block adds a header string : “data:image/png;base64,”.
So before converting it back from base64 to bytes on the Cloud Code side, I would need to strip out this prefix. Once removed, the file saved correctly. Hope this helps.