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.

/
Be the first to leave a comment
You must be Logged on to comment or reply to a post.