Nancy - return pdf stream via ajax - crystal-reports

Is there any sample out there how to return a pdf stream (e.g. generated by Crystal Report) from a nancy module via an ajax request?

I'm not sure what you mean by "ajax request" and why it matters, but recently we had to solve similar problem - i.e. returning pdf, generated from other tool. We ended up using as a template a binary processor, utilizing the content negotiation.
You can modify the binary processor to work with application/pdf MIME type and "pdf" file extensions, so it returns the proper response whenever the request has an Accept header of "application/pdf" or when the request is like http://example.com/reports/report.pdf.
Using this, and assuming you have IReportEngine with Stream GetReportByName(string name), your module will look like (pseudo code):
Get["reports/{reportName}"] = _ => _engine.GetReportByName(_.reportName);

Related

NetSuite RESTlet output pdf

NetSuite Restlet PDF file encoding issue
The above thread seems to be giving a solution to outputing a pdf with a NetSuite RESTlet. As far as I know, you cannot output a pdf from a restlet, so I'm very confused. I am using a restlet to generate a report and the information ultimately needs to output to a pdf so I was trying to see if there was a work around. I tried the answer code from the above thread and I got the expected error:"error code: INVALID_RETURN_DATA_FORMAT error message:Invalid data format. You should return TEXT."
Am I missing something? Is there a way to export xml to a pdf with a NetSuite RESTlet?
The thread you reference discusses how to generate a PDF file in Netsuite. If you want to return a PDF from a RESTLet you will have to return it as a member of a JSON object. e.g.:
var pdfFile = genPDF(); // base this on the sample
return{
fileName: pdfFile.getName(),
fileContent: nlapiEncrypt(pdfFile.getValue(), 'base64')
};
And then your receiver will have to create the actual file.
Recall that RESTLets are for application-to-system communications. If you are trying to return a PDF to a browser you should probably be using a Suitelet.
If this is part of a larger app and you need the RESTLet then review this post: Save base64 string as PDF at client side with JavaScript for options to display the RESTLet response.
Reading through that answer, it appears you'll need to encode/convert the PDF to string format before returning, so you'll need to use base64 encoding.
The NS method nlapiEncrypt(content, 'base64') seems like it might be a good place to start.
Another avenue to investigate, which I haven't tried, is to first save the PDF in the file cabinet, then to return a public link to that file. You'll need to make sure the file has the correct permissions.

Pass rest resource output format in url

AFAIK every resource have a url in REST design. for example /user/28 is url of user with id equal to 28 and /users will return all users.
There are some way to represent output format of the resource:
passing a query parameter like format
specify it using extensions(changing /users url to /users.json to get the users in json format)
specifying the requested format(xml, json, xls, ...) by setting Accept http header.
I search the web and it seems the correct way is setting Accept header.
But if you want to have a http link (specified by href) to download list of users in xls format, you can't!Also if you want to download the xls by the browser, you will encounter many problems(you should use ajax so the xls should download using ajax and etc.)
If it is the best way, what is the solution for download link and if its not, which solution is better?
The Accept header is considered 'more correct', but there are plenty examples of all the options you mention. As far as I can tell, none of them is considered "bad". Personally, I'd say that you should honor and prefer the Accept header, but a format query parameter should override it, if present. The downside of the 'extension' method is that each format results in a different resource, which can get ugly.

BigCommerce API Update Order with PUT

I need to update an order which is done via PUT method passing the order id as part of the https url string and a single parameter, the status_id.
https://mystore.mybigcommerce.com/orders/12345.json
I have tried several methods to pass the status_id value but no matter what I try "status_id=12" or formatted as JSON "{"status_id": 12,}" I always get the same response:
[{"status":415,"message":"The specified input content type is not valid."}]
I have also tried as a POST request passing the JSON or XML code as raw data but that method is not supported.
How am I supposed to pass that field=value pair? can I embed it in the url string?
I also tried it but it wouldn't work for me.
Any ideas?
In case you are wondering I am doing it within FileMaker with TROIUrl plugIn, not a very popular technology, but the GET method retrieving orders works like a charm
TURL_Put( ""; $url ;"status_id=12") (I have also tried other FM plugIns to no avail)
Don't get too caught up in the Filemaker part, I don't expect many people out there to be familiar with BigCommerce and Filemaker. I just need a generic answer.
Thanks
Commandline tool curl is worth a try. It supports put and https.
Mac OS X: curl already installed, call from FileMaker via AppleScript do shell script.
Windows: must be installed, call via Powershell.
It works for me using { "status_id": "3" } which means you probably need to put quotes around the actual number.
Also, it is a PUT operation and application/json which is part of the request content.
The error message received by the OP:
[{"status":415,"message":"The specified input content type is not valid."}]
Is saying that he did not supply the 'Content-Type' header in his request or that the header supplied is for a content type that is not allowed. For the OP's case using JSON he would need to include the header:
Content-Type: application/json
in his HTTPS request. This description can be found along with those of the other status codes you may see here:
https://developer.bigcommerce.com/api/status-codes

Parsing response from the WSDL

I've generated the web service client in eclipse for the OpenCalais WSDL using the "develop" client type. Actually I was following this post so not really going in detail. Now when I get the results this way: new CalaisLocator().getcalaisSoap().enlighten(key, content, requestParams);, I get the String object, containing the response XML. Sure it's possible to parse that XML, but I think there must be some way to do it automatically, e.g. getting the response object in the form of some list whatsoever?
The response from the SOAP interface is already parsed. The englighten() method returns an XML string. When you call it with SOAP, this response is wrapped within even more XML. The SOAP library already parses the outer SOAP XML and returns the result of the enlighten() method, which is also XML.

Is it ok to return application/octet-stream from a REST interface?

Am I breaking any laws in the REST bible by returning application/octet-stream for my responses ? The REST endpoint receives 5 image urls.
{ "image1": "http://ww.o.com/1.gif",
"image2": "http://www.foo.be/2.gif" }
and it will download these and return them as application/octet-stream.
CLARIFICATION: The client that invokes this REST interface is a mobile app. Every additional network connections made will reduce battery life by a few milliamps. I am forced to use REST because it is a company standard. If not, I will do my own binary protocol.
It is not so good, as the client will not know what to do with such binary data except of storing those bytes somewhere or sending them further to some other process (if this is all you need to do with your data, then it is fine).
You may take a look at multipart content types. IMO, a multipart message containing several image/gif parts would be a better alternative.
From the sounds of this, this sounds much more like an RPC call. Specifically, "here's a list of URLs, send me back an archive".
That process is not particularly RESTful, as REST is not an RPC based system.
What you need to do is treat the archives as reources, and a way to create and then serve them up.
For example you could:
POST /archives
Content-Type: application/json
{ "image1": "http://ww.o.com/1.gif",
"image2": "http://www.foo.be/2.gif" }
As a result, you would get
HTTP/1.1 201 Created
Location: http://example.com/archives/1234
Content-Type: application/json
Then, you could make a request to http://example.com:
GET /archives/1234
Accept: multipart/mixed
Here, you will get the actual archive in a single request (like you want), only it's a multipart formatted result. (multipart/x-zip would work too, that's a zip file)
If you did:
GET /archives/1234
Accept: application/json
You would get back the JSON you sent originally (so you could, perhaps, edit and update the archive, something you may not want to support sending up the binary images).
To change it you would simply POST back the update:
PUT /archives/1234
Content-Type: application/json
{ "image1": "http://ww.o.com/1.gif",
"image2": "http://www.foo.be/2.gif",
"image3": "http://www.foo2.foo/4.gif" }
The resource is /archives/1234, that's its name.
It has two representations in this case: the JSON version, and the actual, binary archive. Your service distinguishes between the two using the content type specified in the Accept header. That header is the client telling you what it wants.
When you're done with the archive, simply DELETE it
DELETE /archives/1234
Or you can have the server expire the resource at some later time.
Why not have five separate REST calls?
Seems cleaner and divides more logically. It will also run the downloads in parallel, 2 or more at a time depending on the browser you are using.
They are called REST principles not laws, but no you are not "breaking" them, IMO. REST is about resources being addressable by a URL, and (where appropriate) available in multiple formats. It doesn't say what the format should be. There's a simple description of what REST means in this article.
However, as #Andrey says there are nicer ways to handle sending multiple data objects than inventing your own adhoc format. The Multipart mimeType / format is one alternative, and another is to send the objects packed up as a tar, zip or a similar archive file format.
IMO. the real problem with using "application/octet-stream" and is that it doesn't tell anyone anything about how the data is actually formatted. Rather your client has "know" how it is formatted, and interpret it accordingly. And the problems with inventing your own format are interoperability and (possibly) having to design, implement and maintain libraries to support it, possibly may times over.