sapmentors / cap-community

SAP CAP Community
MIT License
97 stars 26 forks source link

Error on header mapping on v2 proxy for media files #100

Closed jofunkillo closed 3 years ago

jofunkillo commented 4 years ago

I'm working on a documents manager using CAP + freestyle app with an upload collection UI element. The project is totally working now, but to achieve it I had to patch the index.js on the cds-odata-v2-adapter-proxy.

My data structure is having some additional fields I want to fill together with the attachment:

entity DocumentVersion: cuid, managed {
    versionNo: Integer;    
    comment: String; 
    document: Association to one Document;
    filename: String;    
    mimetype : String @Core.IsMediaType;
    content: LargeBinary @Core.MediaType: mimetype;     
    filesize: Integer;    
}

On method onBeforeUploadStarts on my controller implementation I'm passing those fields (versionNo, comment, document_ID, filesize) to the header in order to get them correctly filled in the database entity entry:

var oVersionHeaderField = new sap.m.UploadCollectionParameter({
    name: "versionNo",
    value: "65"
});
oEvent.getParameters().addHeaderParameter(oVersionHeaderField);

var filesize = oEvent.getSource()._getFileUploader().oFileUpload.files[0].size;
var oFileSizeHeaderField = new sap.m.UploadCollectionParameter({
    name: "filesize",
    value: 123432 //filesize
});
oEvent.getParameters().addHeaderParameter(oFileSizeHeaderField);

Those two parameters are the example of the two problems I have found.

First one is having capital letters on the field name, on my example versionNo. The parameter is ignored, because parameters coming from the UI are lowercase converted and the following comparison is not working fine:

// Custom body
Object.keys(headers).forEach((name) => {
     if (definition.elements[name]) {
         body[name] = headers[name];
      }
});

definition.elements does not match with the lowercase version stored on the header, and thus the value of those parameters is ignored.

The second problem is related to the data types. I'm having deserialization issue, no matter how I try to store the value for the filesize. The assignment:

body[name] = headers[name];

is just not having into account this possibility and enter the value '123432' that causes later the deserialization error.

My fix for both issues is like this:

// Custom body
   Object.keys(customBody).forEach((name) => {
       for (const element in definition.elements) {
         if (name === element.toLowerCase()){
          if (definition.elements[element].type === "cds.Integer") {
            body[element] = parseInt(customBody[name],10);
          }
          else {
             body[element] = customBody[name];
          }
       }              
    };
});

Probaby, some other data types may need to be taken into account here.

jofunkillo commented 3 years ago

Just to inform the library has been patched and all problems are solved. More info here