Skip to Content
Technical Articles

Pending Upload using Upload Collection

The upload collection control allows users to upload single or multiple files from a device (desktop, tablet, or phone) to the SAP Fiori app. Typically, uploaded files appear in an Attachments tab. However, files can also be displayed elsewhere.

UploadSet is new controller for handling file uploads, however it is available SAPUI5 1.62 onward and hence in most scenarios UploadCollection has to be used (specially in onPremise solutions).

The UploadCollection control can be used in two different scenarios:

  1. Instant Upload: This scenario allows users to upload single or multiple files from their devices (desktop, PC, tablet, or smartphone) and attach them to the application immediately. The selection and upload process is completed in one step and is automatically triggered by the UploadCollection control.
  2. Upload Pending: With this UploadCollection scenario, you can select attachments and add them to the upload list (multiple selection is possible). You can cancel the upload of one file in this selection without canceling the upload of the other selected files. In a second step, you can upload the selected files. The application triggers the upload with an event.

Upload Pending mode requires manual intervention to manage lifecycle of upload collections. This blog focuses on managing lifecycle in pending upload scenario. Let’s start with understanding the anatomy of Upload collection control and then move on handling the runtime behavior.

 

Anatomy of Upload Collection:

Upload Collection consists of instances of file uploader as items. Below is a basic screen shot of File Uploader,

 

 

 

 

We can click on browse button in a table and add attachments one by one. The file is shown in the local browser but is still not uploaded on the server. Once user clicks on Upload File Upload will start.

Upload Collection creates one instance of file uploader for each attachment. Lets say FileUploader_1 , FileUploader_2  and so on for our convenience. These Browse buttons from File Uploader are shown as + icon at the top for Upload Collection. When user clicks on + button and uploads one file locally , that + icon is hidden and the one for next attachment appears on the screen and so on.

Instant Upload is easier but there could be scenarios where you must use Pending Upload. In our case Document # must be generated. So, actual attachment load can happen only after Document# has been generated. When user clicks on Save button then Document # is generated and passed with attachment details in BeforeUploadStart event.

The most tricky part is to clean the control once upload is complete, so that there is no duplicate entries uploaded in next set of iteration.

 

Handling Life cycle of Pending Upload:

1. Assigning File properties to HTTP header:

Once you upload a new file(s) in upload collection, uploadChange event is triggered. You can assign file parameters in HTTP header parameter “slug”. Also, CSRF token can be assigned for the request.
However, at this stage you don’t have document # for reference and this can only be done once upload operation is starting.

var oFile = oEvent.getParameters().files[0];
//Pass File Name in slug
var oCustomerHeaderSlug = new sap.m.UploadCollectionParameter({name: "slug", value: "FileName=" + oFile.name
			});
oEvent.getSource().addHeaderParameter(oCustomerHeaderSlug);
//Pass Mime Type in slug
oCustomerHeaderSlug = new sap.m.UploadCollectionParameter({name: "slug",value: "MimeType=" + oFile.type});
oEvent.getSource().addHeaderParameter(oCustomerHeaderSlug);
//Assign X-CSRF Token in header
if (!this.attachmentModelCSRFToken) {
var attachmentModel = this.getView().getModel("AttachmentModel");
	attachmentModel.refreshSecurityToken();
	this.attachmentModelCSRFToken = attachmentModel.getHeaders()["x-csrf-token"];
}
var oCustomerHeaderToken = new sap.m.UploadCollectionParameter({name: "x-csrf-token",value: this.attachmentModelCSRFToken
			});
oEvent.getSource().addHeaderParameter(oCustomerHeaderToken);

Please note that you can add multiple Header parameters with same key “slug”. They will be converted as comma separated string when the request is sent to backend.
e.g. slug = “FileName=DummyFile.pdf,MimeType=application/pdf”

2. Assigning Document # to HTTP Header:

As explained, we must upload the files in reference of a document number that will be generated in runtime. Once this document is created, upload should be triggered.

this.getView().byId("UploadCollection").upload();

For each file, beforeUploadStarts event is triggered. Document # can be set at this point.

var oCustomerHeaderSlug = new sap.m.UploadCollectionParameter({
			name: "slug",
			value: "DocumentNum=" + this.oDocumentNumber
			});
oEvent.getParameters().addHeaderParameter(oCustomerHeaderSlug);

3. Handling Upload Completion:

Once upload is completed, uploadComplete event is triggered. Following activity is required:-

  • Check status of upload completion
  • If successfully upload, remove the underlying FileUpload control instance from collection.
    In case not removed the next run of app (in same session) may upload the file again though it will not be visible in UI.
  • If failed, allow user to take corrective actions (retry, error handling etc)
onUploadComplete: function (oEvent) {
var oUploadCollection = oEvent.getSource();
	//Uploaded ID
	var sEventUploaderID = oEvent.getParameters().getParameters().id;
	
	
//Reference to File Uploader instance
	var oParam = oEvent.getParameter("files")[0];
	//Upload is successful
	if (oParam.status === 201) {
		//Log success message
		this.util.addSuccessMessage(this._oView, "FileName: " + oParam.fileName, "Attachment Uploaded Successfully",
					"Attachment Uploaded Successfully");
		// Remove the File Uploader instance from upload collection reference
for (var i = 0; i < oUploadCollection._aFileUploadersForPendingUpload.length; i++) {
var sPendingUploadederID = oUploadCollection._aFileUploadersForPendingUpload[i].oFileUpload.id;
			if (sPendingUploadederID.includes(sEventUploaderID)) {
				oUploadCollection._aFileUploadersForPendingUpload[i].destroy();
				oUploadCollection._aFileUploadersForPendingUpload.splice([i], 1);
			}
		}
	}
	// Upload Failed  Time Out scenario
	else if (oParam.status === 504) {
		// Log error message
		this.util.addErrorMessage(this._oView, null, "FileName: " + oParam.fileName, "Attachment Upload Failed",
			oParam.responseRaw);
		} 
// Upload Failed  Application Error
else {
		// Log error message
		this.util.addErrorMessage(this._oView, null, "FileName: " + oParam.fileName, "Attachment Upload Failed",
					oParam.response);
			}
}

Conclusion:

Pending Upload of files is very common requirement. This blog will help users to handle lifecycle of pending upload and avoid common pitfalls.

/
8 Comments
You must be Logged on to comment or reply to a post.
  • Hello,

    thanks for this blog entry.

     

    But how about the GW oData implementation?

    What has to be implemented there? Just the CREATE_STREAM Method?

    I got a Post to a certain entity_set here.

    Thanks.

    Regards.

     

    Andreas

      • Hello!

        Do you have an example implementation for this CREATE_STREAM in context with the UploaderCollection?

        I’m facing currently a lot of issues in order to get it to work.

        First of all a 405 and then a 500 server error.

        Thanks a lot!

        Regards

        Andreas

  • Hi Prajna,

    Thanks for detailed information.

    we are using uploadcollection  UI element, we have requirement of showing existing document and enable user to add new documents also. existing document we are showing as uploadcollection items links, when user clicks it will download from the content repository.

    Scenario One (user will not add any attachments) :

    upload collection shows existing files, user will not attach any new document manually. is it possible to upload existing files again using upload collection.

    Note : (i tired but no existing documents are uploaded)

    Scenario Two ( User will add new attachcmetns manually)

    initially uploadcollection  will show existing document and user have option add new document manually, the user click upload , Is it possiible to upload all the documents again (old and newly added) to backend again? i tired , but identified only new documents are uploading not the existing documents which we showed as links in upload collection?

    is it the standard behavior of upload collection? is it possible to upload existing documents along with new documents?

    Advance thanks for your help.

    Regards,

    Srinivasu.Y

    • Hello Srinivasu,

      If there is no change in upload collection set, it will not send the files again to be uploaded. This is not logical and the same concept is used in normal odata v2 services as well where submit operations send back the changes only.

       

      Regards,

      Prajna Parmita

    • In this scenario, we are getting document number as success response to create operation from oData. Same is used when adding slug parameters.

       

      Regards,

      Prajna Parmita

  • Thanks for the blog … May i know where the upload is called ?

    this.getView().byId("UploadCollection").upload();

    inside onChange ? in docs they mentioned in onStartUpload , could you please guide me with this ..

    One more quick question – What is the name (Unique control name for identification on the server side after sending data to the server) ??

    I have been trying using uploadCollection[] by referring in chrome dev tools , i get an empty array or saying current request is not a multipart request .. Thanks 🙂