Upload Files in UI5 without using Create Stream in Gateway - odata

I'm building an UI5 application where I need to send several entities to backend at the same time (I'm using create_deep_entity method for that).
I'm using the concept of master-detail (father and children). One of these children is a set of files which need to be sent to backend at the same request as other entities (I want to send them together on create deep).
Is there a way I can use an UI5 component (file upload maybe?) to read the files and send to backend without using create stream method (it must be sent along with other entities on create deep)?
Apreciate your input on this

There is no standard UI5 component that can be used to upload files and send them to the backend without using the create stream method. However, you can create a custom component that will allow you to do this.
You will need to create a custom component that will read the files and send them to the backend. This will require some custom coding.
coding example:
var oFileUploader = new sap.ui.unified.FileUploader({
uploadUrl: "your_backend_url",
uploadOnChange: false,
multiple: true
});
oFileUploader.attachChange(function(oEvent){
var aFiles = oEvent.getParameter("files");
for(var i=0; i<aFiles.length; i++){
var oFile = aFiles[i];
var oRequest = new XMLHttpRequest();
oRequest.open("POST", "your_backend_url");
var oFormData = new FormData();
oFormData.append("file", oFile);
oRequest.send(oFormData);
}
});

Related

Data Gets Converted when passed to CREATE_STREAM

I have created an UI5 Application to read a file and send it to a custom OData Service in the Backend.
onUploadFile: function() {
var oFileUpload =
this.getView().byId("fileUploaderFS");
var domRef = oFileUpload.getFocusDomRef();
var file = domRef.files[0];
var that = this;
var reader = new FileReader();
var ftype = file.type;
reader.readAsArrayBuffer(file);
reader.onload = function(evt) {
var vContent = evt.currentTarget.result
console.log(vContent);
var hex = that.buf2hex(vContent);
that.updateFile(hex, ftype);
}
},
buf2hex: function(buffer) {
return [...new Uint8Array(buffer)]
.map(x => x.toString(16).padStart(2, '0'))
.join('');
}
When I print the content of hex on the console before sending it to the backend, the data starts with 89504e470d0a1a0a0000000d49484 ....
Even before sending the data in the payload to Odata Service it shows the correct data
Here is the Odata Service
Inside the Create Stream the data when received, is getting converted into something else. As a result the image that has been saved is not opening.
I tried to change the Data Type of Content in SEGW to Binary and it did not work. I also tried to convert the data in the create_stream but in vain. At last I tried reading the data in UI5 in different formats but of no use.
This whole Odata service works perfectly fine when I load the data through Postman Application.
Please help me resolve this Issue. Thanks In Advance.
The sap.ui.unified.FileUploader has everything built in. No need for conversions from Buffer to hex.
Make sure that your FileUploader knows where to upload the file
<unified:FileUploader xmlns:unified="sap.ui.unified"
id="fileUploaderFS"
uploadUrl="/sap/opu/odata/sap/Z_TEST_SRV/FileSet"
/>
The attribute uploadUrl points to the media entity for which you implemented the create_stream method.
Then when the upload is triggered via button press, simply get the FileUploader, set the token (for security reasons when doing a POST request), and fire the upload method.
onUploadFile: function () {
const oFileUpload = this.getView().byId("fileUploaderFS");
const sToken = this.getModel("nameOfTheModel").getSecurityToken();
const oTokenParam = new FileUploaderParameter({
name: "x-csrf-token",
value: sToken
});
oFileUpload.removeAllHeaderParameters()
oFileUpload.addHeaderParameter(oTokenParam);
oFileUpload.upload();
}
To use FileUploaderParameter, make sure to import it at the beginning:
sap.ui.define([
// ...,
"sap/ui/unified/FileUploaderParameter"
], function (/*..., */FileUploaderParameter) {
// ...
Now about your File entity. When working with it via create_stream or read_stream, you don't use the entity structure but is_media_resource. This means your entity doesn't need a property content. Or most of the other properties (except a unique id and the mime type). All other properties would only be used if you want to do one of the CRUD methods (which happens almost never when dealing with streams).

SAPUI5 ODataModel metadata $format=xml

i am trying to connect sapui5/openui5 ODataModel to an odata-server. I want to use a nodejs server with package simple-odata-server. Unfortunately this odata server provides metadata only in xml-format. But sapui5 tries to load metadata in json-format.
Before i switch to another odata server, i want to check, wether sapui5 can load metadata in xml-format. I tried to create the model with several parameters, but ODataModel still tries to load metadata as json.
var oModel = new ODataModel("/odata", {
"metadataUrlParams": "$format=xml",
"json": false
});
Does anybody know, wether i can switch to $format=xml
Thanks in advance,
Torsten
As far as I know the OData protocol metadata is always provided as XML, never seen metadata in JSON format. Also my n-odata-server Qualiture mentioned in the comment above does it. But I never had problems with SAPUI5. It requests the metadata, gets the xml stream and works with it.
Since the metadataUrlParams parameter is of type map I'd suppose it would at least do what you intend like this:
var oModel = new ODataModel("/odata", {
"metadataUrlParams": {
"$format": "xml"
}
});
https://sapui5.hana.ondemand.com/sdk/#docs/api/symbols/sap.ui.model.odata.ODataModel.html#constructor

Attach POST data to BackgroundDownloader

I am implementing a Windows Phone 8.1 application that creates BackgroundDownloaders to restore cloud files back to the phone.
The cloud requires to POST the file ID as an additional JSON POST request and i cannot find a way to define it the BackgroundDownloader object.
Any ideas?
The way to do it is by creating a temp file to hold the JSON post data and send it to the CreateDownload function (as the last StorageFile parameter).
In addition, i added a Content-Type header to describe it (for me it is application/x-www-form-urlencoded) and add it with SetRequestHeader.
//set the Content-Type header
BackgroundDownloader^ downloader = ref new BackgroundDownloader();
Platform::String^ SKey2 = ref new Platform::String(L"Content-Type");
Platform::String^ SValue2 = ref new Platform::String(L"application/x-www-form-urlencoded");
downloader->SetRequestHeader(SKey2, SValue2);
//Create a temporary file and write the POST data into it
StorageFile^ postDataFile = nullptr;
....
//Call CreateDownload with the postDataFile
downloader->CreateDownload(uri, file, postDataFile);
That worked for me.

Is there a simple way to share session data stored in Redis between Rails and Node.js application?

I have a Rails 3.2 application that uses Redis as it's session store. Now I'm about to write a part of new functionality in Node.js, and I want to be able to share session information between the two apps.
What I can do manually is read the _session_id cookie, and then read from a Redis key named rack:session:session_id, but this looks kind of like a hack-ish solution.
Is there a better way to share sessions between Node.js and Rails?
I have done this but it does require making your own forks of things
Firstly you need to make the session key the same name. That's the easiest job.
Next I created a fork of the redis-store gem and modified where the marshalling. I need to talk json on both sides because finding a ruby style marshal module for javascript is not easy. The file where I alter marshalling
I also needed to replace the session middleware portion of connect. The hash that is created is very specific and doesn't match the one rails creates. I will need to leave this to you to work out because there might be a nicer way. I could have forked connect but instead I extracted a copy of connect > middleware > session out and required my own in.
You'll notice how the original adds in a base variable which aren't present in the rails version. Plus you need to handle the case when rails has created a session instead of node, that is what the generateCookie function does.
/***** ORIGINAL *****/
// session hashing function
store.hash = function(req, base) {
return crypto
.createHmac('sha256', secret)
.update(base + fingerprint(req))
.digest('base64')
.replace(/=*$/, '');
};
// generates the new session
store.generate = function(req){
var base = utils.uid(24);
var sessionID = base + '.' + store.hash(req, base);
req.sessionID = sessionID;
req.session = new Session(req);
req.session.cookie = new Cookie(cookie);
};
/***** MODIFIED *****/
// session hashing function
store.hash = function(req, base) {
return crypto
.createHmac('sha1', secret)
.update(base)
.digest('base64')
.replace(/=*$/, '');
};
// generates the new session
store.generate = function(req){
var base = utils.uid(24);
var sessionID = store.hash(req, base);
req.sessionID = sessionID;
req.session = new Session(req);
req.session.cookie = new Cookie(cookie);
};
// generate a new cookie for a pre-existing session from rails without session.cookie
// it must not be a Cookie object (it breaks the merging of cookies)
store.generateCookie = function(sess){
newBlankCookie = new Cookie(cookie);
sess.cookie = newBlankCookie.toJSON();
};
//... at the end of the session.js file
// populate req.session
} else {
if ('undefined' == typeof sess.cookie) store.generateCookie(sess);
store.createSession(req, sess);
next();
}
I hope this works for you. It took me quite a bit of digging around to make them talk the same.
I found an issue as well with flash messages being stored in json. Hopefully you don't find that one. Flash messages have a special object structure that json blows away when serializing. When the flash message is restored from the session you might not have a proper flash object. I needed to patch for this too.
This may be completely unhelpful if you're not planning on using this, but all of my session experience with node is through using Connect. You could use the connect session middlewhere and change the key id:
http://www.senchalabs.org/connect/session.html#session
and use this module to use redis as your session store:
https://github.com/visionmedia/connect-redis
I've never setup something like what your describing though, there may be some necessary hacking.

WebRequest to download XML Feed

This is my first time working with a webservice and I tried looking up all the resources on the web but I wasn't able to get it to work.
I have to use this XML in my windows phone application and I want the application to retrieve it when the user wants to. I know how to parse the XML but I am just not able to get the XML from the XML feed.
There are lots of tutorials for this type of problem available on the wider web.
For example, try the 3 line solution from: http://www.codeproject.com/Articles/156610/WP7-WebClient-vs-HttpWebRequest
var client = new WebClient();
client.DownloadStringCompleted += (s, ev) => { responseTextBlock.Text = ev.Result; };
client.DownloadStringAsync(new Uri("http://www.sherdog.com/rss/news.xml"));

Resources