How-to Upload an Image with OutSystems (Beginner)

Database Structure

Ok, let’s say that you have an Entity called Person and you need to upload an image/photo for each Person’s record. You probably will not need to use that photo every time that you access Person’s Entity, so it’s best practice (and specially best performance) if you create a new Entity attribute with the same Id as the Person’s Entity Identifier and a Binary Data attribute to save the file, this will avoid that the images are loaded every time that you access Person’s Entity.

Database should look like the image below.


Steps

  1. Create an Entity with the primary key being of the type Person’s Identifier (establishing the relationship between a Person and his photo) and a Binary Data attribute to save the image file.



  1. In order to upload an image you will need to use the upload widget from the toolbox.



  1. You will also need a button or a link to perform the action to save the image file in the database. Here you need to have one thing in consideration: in order that the upload widget works the button/link method can’t be Ajax Submit.



  1. You can just double-click the button and an action will be created (or you can create it manually) to save the data.

  2. Create a local variable (in our case of the type PersonPhoto) to hold the data.

  3. Assign an Identifier to the local PersonPhoto.Id (in our case it’s the PersonId received by the page), and the Binary Data from the Upload Widget Content attribute to Photo attribute in the PersonPhoto Entity. (This is just an example you will need to adapt this to your purposes)

  4. Now you can just drop the CreateOrUpdatePersonPhoto under the assign and set the source to the local variable created before.

Your action should look like this.



Now the upload of the image should be working, but it will be useless if we can’t see the image, so in the next steps we will explain how to show an image from the database.



How to show image from the database  

  1. To show the image we will use the Image Widget from the toolbox, just drag and drop it wherever you want.



2. After you do it a window will appear, and you should choose some default image to be displayed when an image doesn’t exist in the database.



  1. Since you want the image to be set from the database you should change the widget attribute type to Database. (check picture below)

  2. Some attributes will be unlocked and the Filename and the Attribute will appear as mandatory. So you need to set those. In the Filename, if you have the image file name in the database you can pass that parameter here, since we aren’t saving the image file names we just pass an empty string (“”), and in the Attribute we will pass the type of attribute that the widget will receive that should be of Binary Data type. (check picture below)

  3. After you set the Attribute the Entity Identifier will appear as mandatory, you need to pass the Identifier of the image that you want to show (so in our case the Identifier is the same as the associated Person’s Identifier), and the widget will then find automatically the corresponding image.



And it’s done now you should be able to upload and see your images.
(sample attached)



Thanks João, next time the question comes up we can just point here :).

João Vicente wrote:

I tried this approach to upload image but unfortunately, I am getting this error.

Regards,

Pankaj Pant


Hi Pankaj,

First, please don't fully quote the previous post, this makes it very difficult to read your post. If possible, please edit your post and remove the quoted stuff.

Secondly, your error indicates that you are trying to store the image to the PersonPhoto Entity, without setting the PersonId.

Solution

Hi pankaj pant!

Sorry, I should have talked about that in the post, but in this case, you need to create a person before you upload an image, I made some changes in the app to make it more explicit, please see the oml again. 

Best regards,

João Vicente.

Solution

João Vicente wrote:

Hi pankaj pant!

Sorry, I should have talked about that in the post, but in this case, you need to create a person before you upload an image, I made some changes in the app to make it more explicit, please see the oml again. 

Best regards,

João Vicente.

Thank you..


João Vicente wrote:

Hi pankaj pant!

Sorry, I should have talked about that in the post, but in this case, you need to create a person before you upload an image, I made some changes in the app to make it more explicit, please see the oml again. 

Best regards,

João Vicente.

Hi Vincent's,

Even from your updated oml I am facing that foreign key error .


I am also facing the same issue

Hi Ummul,

To read a "FOREIGN KEY constraint" error from the database, you need to know how to parse the error message, and especially the "OSFRK_" identifier. This is the actual foreign key constraint in the database, preventing you from inserting a record that has no foreign key identifier, in case it is a mandatory Attribute. Here is how it parses:

OSFRK indicates that it is an OutSystems FoReign Key. OSUSR_CJM_PERSONPHOTO is the database table that contains the foreign key. "OSUSR" is a generic indication for OutSystems USeR tables (a.k.a. Entities), "CJM" is a hashcode for the UploadImage Module. PERSONPHOTO corresponds to the PersonPhoto Entity. OSUSR_CJM_PERSON_ID indicates that there's an Attribute in the PersonPhoto Entity that refers to a Person Id.

Next, it tells you in what database the error occured (which is not interesting in this case), and then it lists the table (Entity), dbo.OSUSR_CJM_PERSON (so it pertains to the Person Entity), and the column "ID". This means that there's no corresponding "Id" in "Person" to the corresponding Attribute you're trying to store in PersonPhoto.

Looking at you data model, The Id of PersonPhoto is of type Person Identifier, so after saving a Person, you need to store the Id in PersonPhoto.Id. Currently, you assign EmployeeId, but if the Screen was started creating a new employee, EmployeeId is still empty. So you need to assign the Id of the CreateOrUpdatePerson in the Save Screen Action to EmployeeId, and it should work.

Kilian Hekhuis wrote:

Hi Ummul,

To read a "FOREIGN KEY constraint" error from the database, you need to know how to parse the error message, and especially the "OSFRK_" identifier. This is the actual foreign key constraint in the database, preventing you from inserting a record that has no foreign key identifier, in case it is a mandatory Attribute. Here is how it parses:

OSFRK indicates that it is an OutSystems FoReign Key. OSUSR_CJM_PERSONPHOTO is the database table that contains the foreign key. "OSUSR" is a generic indication for OutSystems USeR tables (a.k.a. Entities), "CJM" is a hashcode for the UploadImage Module. PERSONPHOTO corresponds to the PersonPhoto Entity. OSUSR_CJM_PERSON_ID indicates that there's an Attribute in the PersonPhoto Entity that refers to a Person Id.

Next, it tells you in what database the error occured (which is not interesting in this case), and then it lists the table (Entity), dbo.OSUSR_CJM_PERSON (so it pertains to the Person Entity), and the column "ID". This means that there's no corresponding "Id" in "Person" to the corresponding Attribute you're trying to store in PersonPhoto.

Looking at you data model, The Id of PersonPhoto is of type Person Identifier, so after saving a Person, you need to store the Id in PersonPhoto.Id. Currently, you assign EmployeeId, but if the Screen was started creating a new employee, EmployeeId is still empty. So you need to assign the Id of the CreateOrUpdatePerson in the Save Screen Action to EmployeeId, and it should work.

Hi Killan ,

Thanks for the input the image is saving now but it isn't visible in the screen. I have given the filename as "" .

Hi Ummul,

You need to refresh the Screen to show the image. Since an upload button cannot use the Ajax Submit, you need to end the flow with a redirect to the same Screen.

Kilian Hekhuis wrote:

Hi Ummul,

You need to refresh the Screen to show the image. Since an upload button cannot use the Ajax Submit, you need to end the flow with a redirect to the same Screen.


I have done that also but it isnt comng can you look into my oml and tell where i am doing mistake

Hi Ummul,

Rule #1\: always look at the warnings! I opened your Module and I immediately saw yellow warning squares, here:

and here:

When you hover with the mouse, or look at the TrueChange tab, you'll see this:

EmployeeId is a Person Identifier, but the Entity Identifier for that image should be a PersonPhoto Identifier.

Hi :) When I try to follow your steps I cannot set my local photo variable as a source for CreateOrUpdate, as it wants a record instead of a binary file. I believe I did set the other directions correctly. Can you help me out?


Hi Eline,

What are you trying to do there? CreateOrUpdateMedewerkerPicture needs a Record of type MedewerkerPicture, as the error messages indicates. Yet you try to pass "photo", which is of type Binary Data.

Kilian Hekhuis wrote:

Hi Eline,

What are you trying to do there? CreateOrUpdateMedewerkerPicture needs a Record of type MedewerkerPicture, as the error messages indicates. Yet you try to pass "photo", which is of type Binary Data.

Thanks for the fast reply! I am building an employee database in which the employee should upload a picture of him/herself. I understand that CreateOrUpdateMedewerkerPicture wants to update the entire record, but it only needs to update the picture of this record (which is connected to the employee info entity) 

As stated in the original post, I created a local variable to hold the photo (binary data). When I use another type of data it gives an error with the upload widget. So the button assigns the photo to the current medewerkerPicture.picture

 


As I set the Current.medewerkerPicture.picture as the source for the CreateOrUpdateMedewerkerPicture , the button won't work.. Can you explain what I am doing wrong?


Thank you in advance :) 

Hi Eline,

Next time, I'd ask you to create a new topic, since this has little to do with the original.

For now, a few comments:

  • You cannot update only a single Attribute of an Entity. Although databases allow this on a low level, with OutSystems you always need to provide the entire record. If you don't want to change certain Attributes, just supply the original value.
  • In this specific case, it seems that the Picture attribute is the only Attribute of MedewerkerPicture, so I'm not sure where your confusion stems from.
  • Since it seems, from the Assign image, you already assign the photo (and I assume the Id as well, but the picture is cut-off so I cannot see), why don't you pass the Current.MedewerkerPicture to the CreateOrUpdateMedewerkerPicture?

Kilian Hekhuis wrote:

Hi Eline,

Next time, I'd ask you to create a new topic, since this has little to do with the original.

For now, a few comments:

  • You cannot update only a single Attribute of an Entity. Although databases allow this on a low level, with OutSystems you always need to provide the entire record. If you don't want to change certain Attributes, just supply the original value.
  • In this specific case, it seems that the Picture attribute is the only Attribute of MedewerkerPicture, so I'm not sure where your confusion stems from.
  • Since it seems, from the Assign image, you already assign the photo (and I assume the Id as well, but the picture is cut-off so I cannot see), why don't you pass the Current.MedewerkerPicture to the CreateOrUpdateMedewerkerPicture?

Thanks Kilian, I'll take your advise into account :)