How to parse XML from Rails in Flex - ruby-on-rails

I want to upload a file(photo) from Flex to Rails and then send a response back to the server in XML (contains photo URL and ID). I'm sending from my Rails server some XML as follows:
render(:xml => {:id => #photo.id,
:photoURL => #photo.URL,
:thumbPhotoURL => #photo.thumbURL})
This is sent through FileReference object through fileReference.upload()
I try to render it in the complete handler:
fileReference.addEventListener(Event.COMPLETE,function(event:Event):void {
var xml:XML = new XML(event.target.data);
......
it doesn't seem to parse XML properly. I have used similar code before with URLLoader and it worked. Any ideas?

May i ask why you're converting the data to a ByteArray? URLLoader actually has a great property called dataFormat which you can use to specify the way that Flash will handle the loading. You can choose between binary, text or url-encoded variables.
Like Amarghosh said, you're probably better off using the URLLoader for working with XML.

FileReference is for transferring files between user's hard disk and the server - the upload() function is for sending a file from user's machine to the server.
Use URLLoader to load xml from the server to your flex application
var ldr:URLLoader = new URLLoader();
ldr.addEventListener(Event.COMPLETE, onLoad);
ldr.load(new URLRequest(url));
function onLoad(e:Event):void
{
var loadedText:String = URLLoader(e.target).data;
trace(loadedText);
var xml:XML = new XML(loadedText);
trace(xml.toXMLString());
}

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).

WebAPI: Upload picture & get byte array

I want the user to be able to upload a file via my application. I don't have DB access, all my data calls get completed via a web-service that another person is writing. I needed to secure the web service, so I've consumed it & exposed it via WebAPI, & added OAuth security.
Now to my problem.
I've written the following.
public Task<FileResult> Post()
{
if (Request.Content.IsMimeMultipartContent())
{
var task = Request.Content.ReadAsByteArrayAsync().ContinueWith(
o =>
{
var result = this.Client.UploadPicture(this.UserId, o.Result);
if (result.ResultCode == 0)
{
return new FileResult()
{
Message = "Success",
FileId = result.ServerId
};
}
throw new HttpResponseException(...);
});
return task;
}
...
}
I'm pretty much a noob when it comes to WebAPI & multithreading (I'm not sure why this needs to be handled async? I'm sure there is a reason, but for now I'd just like a working example and get to the why later..).
My code is loosely based on some R&D & samples I've found on the net, but i haven't come across a scenario like I'm needing to complete... Yet it doesn't seem like I'm doing something out of the ordinary...
Upload a file to the server, and pass the image byte[] object to either sql or another service?
In this line
var result = this.Client.UploadPicture(this.UserId, o.Result);
I'm uploading a byte[] array of something....
Then later (the retrieval method works, I've managed to retrieve & view a test image)
When retrieving the byte array of the "image" i uploaded i get an array of idk what.. EG, i get a valid result of something, but it ain't no picture. Which leads me to believe that the uploaded data is bogus :|
O_o
How to get the image byte[]?
Mime Multipart is more than just your array of bytes. It also has metadata and boundary stuff. You need to treat it as MultiPartContent and then extract the image byte array out of that.
Filip has a blog post on the subject here.

ASP.NET Web API, unexpected end of MIME multi-part stream when uploading from Flex FileReference

Following the tutorial found on ASP.NET, implemented a Web API controller method for doing asynchronous file uploads that looks like this:
public Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
// Read the form data and return an async task.
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
return Request.CreateResponse(HttpStatusCode.OK);
});
return task;
}
Uploading a file via a standard multipart HTML form works perfectly. However, when another developer attempts to upload a file via multipart form constructed by Flex's FileReference class, an error is thrown:
Unexpected end of MIME multipart stream. MIME multipart message is not complete.
I have no idea if the problem lies in Web API or Flex. I've found some sort of related fixes that had no affect (Multipart form POST using ASP.Net Web API), and more recently this one ("MIME multipart stream. MIME multipart message is not complete" error on webapi upload). If the second link holds true, does anyone know if it's out in the current release of Web API available via Nuget? The discussion was in May, the most recent release from Nuget was August, so I assume this fix was deployed already, and is not the root cause of my issue.
I had the same problem with MVC4, but Will is correct, add a name to your input.....
<input type="file" id="fileInput" name="fileInput"/>
and all the magic is back up and working!
I had the same problem with flex. And below is the code that solved it. Basically I used a custom stream to append the newline that asp.net web api is expecting.
Stream reqStream = Request.Content.ReadAsStreamAsync().Result;
MemoryStream tempStream = new MemoryStream();
reqStream.CopyTo(tempStream);
tempStream.Seek(0, SeekOrigin.End);
StreamWriter writer = new StreamWriter(tempStream);
writer.WriteLine();
writer.Flush();
tempStream.Position = 0;
StreamContent streamContent = new StreamContent(tempStream);
foreach(var header in Request.Content.Headers)
{
streamContent.Headers.Add(header.Key, header.Value);
}
// Read the form data and return an async task.
await streamContent.ReadAsMultipartAsync(provider);
Hope this helps.
Reading through your existing research and following through to the codeplex issue reported it looks like someone else confirmed this issue to still exist in September.
They believe that MVC 4 fails to parse uploads without a terminating "\r\n".
The issue is really simple but extremely hard to fix. The problem is that Uploadify does > not add an "\r\n" at the end of the MultiPartForm message
http://aspnetwebstack.codeplex.com/discussions/354215
It may be worth checking that the Flex upload adds the "\r\n"
For those landing here googling:
Unexpected end of MIME multipart stream. MIME multipart message is not complete.
Reading the request stream more than once will also cause this exception. I struggled with it for hours until I found a source explaining that the request stream only could be read once.
In my case, I combined trying to read the request stream using a MultipartMemoryStreamProvider and at the same time letting ASP.NET do some magic for me by specifying parameters (coming from the request body) for my api method.
Make sure the virtual directory ("~/App_Data" directory as below example) where the image files are first uploaded are physically existance. When you publish the project, it may not be in the output files.
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
I just removed my headers I was setting on my post method which ended up solving this issue.
The problem is this line:
string root = HttpContext.Current.Server.MapPath("~/App_Data");
It will only work in localhost, you can use HostingEnvironment.MapPath instead in any context where System.Web objects like HttpContext.Current are not available (e.g also from a static method).
var mappedPath = System.Web.Hosting.HostingEnvironment.MapPath("~/SomePath");
See also What is the difference between Server.MapPath and HostingEnvironment.MapPath?
Reference to this answer How to do a Server Map Path.

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"));

OS X Wiki/Blog Server API

I'm working on a client app for iOS to edit the built-in Wiki/Blog on Mac OS X Server (Snow Leopard & Lion).
It seems that we are able to use MetaWeblog , Atom API(I've tried but failed) or XML-RPC.
However, I can't find any API document for it.
So my question is, where can I find the documents, or some open source samples?
All samples I found can't deal with the OS X Server.
Much appreciate!
Peak
Update:
Heres the standard structure of the Wiki system:
I can't even get the list of the 'group_name' under ~/Groups/
The javascript source code for the wiki is not obfuscated, and it seems simple enough to serve as documentation. For example, the authentication process:
sendAuthenticationPlain: function() {
$('webauth').addClassName('verifying').removeClassName('error');
var username = $F('username');
var password = $F('password');
var csrf = $F('authenticity_token');
var plainResponse = "username="+username+"&password="+password
this.setRememberMeCookie();
var ajaxReq = new Ajax.Request(window.location.protocol + '//' + window.location.host + "/auth/plain_login", {
method: 'post',
requestHeaders: {'X-CSRF-Token': csrf},
onComplete: this.gotAuthentication.bind(this),
postBody: plainResponse
});
return false;
},
gotAuthentication: function(origRequest) {
if (origRequest.responseJSON) {
var jsonObject = origRequest.responseJSON
if (jsonObject['success']) {
var redirect = jsonObject['redirect'];
var authToken = jsonObject['auth_token'];
this.successCallback(authToken, redirect);
} else {
var errorString = jsonObject['error_string']
this.failureCallback(errorString);
}
}
},
So you send a POST request to auth/plain_login, containing just the username/password in the POST data and an X-CSRF-Token header who's value comes from the <input type="hidden" name="authenticity_token" /> element on the page. The server returns a JSON string containing 'success' boolean.
You can also use safari/chrome's developer tools to monitor ajax requests to/from the server, for example this is the JSON contents of a PUT request to save a wiki page:
I'm working on the latest Lion server, for an access via an app. The structure of the Lion server web service is based on ruby on rails, and is easy to understand ( I have no ruby experience before). However, the whole system(for the implemented part) is not designed for API access. For example, the auth system is based on Cookie authentication(session id or something). not all the output of the request has a json response. Not any failed request responses with a json body.
all the work need to be done by ur self.
The first is to authenticate with the server. all the process is exposed to you:
'wiki/api/csrf' to get the X-CSRF-Token value
'auth/challenge_advanced?username=xxxx' to get a challenge parameters
'auth/digest_login' to use md5-sess digest to login
while, the md5-sess digest is calculated by your own code following to the digest.js (objective-c for me, with CC_md5 lib)
then you can added json render support to ur required controllers, such as,
respond_to do |format|
format.html
format.js { render_js_pagination_response(#search, 'people/entitylist_item') }
format.json { #new added json support
rs = []
#search.results.each do |r|
nr = filterUserInfo r # I only need some of the all properties
rs.push nr
end
render :json => rs
}
end
One important thing is, the lion server use web auth/cookie to authorize an access, so your request lib/api must handle the cookies.
all above is a simplest solution the the api/json access, but not the best one. U had better to re-work all access progress to suit the api access.
BTW: u can copy the whole /usr/share/collabd/ into ur own project's dir, then modify all /your projects path/collab/coreclient/config/collabcore{1,2,3,4}.yml, change the production to development.
so u can start a development server app under collab/coreclient with:
sudo -u _teamsserver thin start
access to the server thru http://localhost:3000

Resources