Kohana 3, serve image stored in a database - kohana

I had this working on kohana 2, but in kohana 3 it doesn't.
To serve an image stored as BLOB in a database, I did the following:
1- A controller to which I request what image do I want. I connects to the database, using a model of course, and serve the image using a view.
$prod = ORM::factory('product',$idx);
$img = new View('image');
$img->pic = $prod->getImage();
2-The model has a little trick to get this working:
public function getImage()
{
return imagecreatefromstring($this->image);
}
image is the blob column where I store the picture I want to serve.
3- In the view:
I set the content-type header and then serve the image
header('content-type: image/png; charset=UTF-8');
imagepng($pic);
This worked in Kohana 2, but in KO3 it doesn't,
I'm trying to use $response->send_file(), but I'm getting lost

First, you should never send headers with header() unless you're hacking the fw. Ko3.1 nicely separates Request from Response and the latter is the one responsible for response headers / everything else (both of them are written pretty much following the RFC 2616).
Secondly, there is absolutelly no need for a view file in this case, Response::$_body is what the current response object returns.
Response::send_file() returns the response as download, I suppose that's not what you're trying to accomplish?
So, you need something like this (modify to your own needs):
public function action_image($id)
{
$image = ORM::factory('product', $id);
if ( ! $image->loaded()) // ... 404 ?
$this->response
->headers('Content-Type','image/png')
->body($image->image)
->check_cache(NULL, $this->request); // 304 ?
}

Related

AVPlayer Not Able to Handle Relative Path URL in HLS Streams

We are running into an issue that seems unique to AVPlayer. We've built a new architecture for our HLS streams which makes use of relative URLs. We can play these channels on a number of other players just fine, but when trying to build using AVPlayer, the channel gets 400 errors requesting either child manifests/segments with relative URLs.
Using curl, we are able to get a 200 success by getting to a url like: something.com/segmentfolder/../../abcd1234/videosegment_01.mp4
Curl is smart enough to get rid of the ../../ and create a valid path so the actual request (which can be seen using curl -v) looks something like: something.com/abcd1234/videosegment_01.mp4
Great. But AVPlayer doesn't do this. So it makes the request as is, which leads to a 400 error and it can't download the segment.
We were able to simulate this problem with Swift playground fairly easily with this code:
let hlsurl = URL(string: "website.com/segmentfolder/../../abc1234/videosegment.mp4")!
print(hlsurl)
print(hlsurl.standardized)
The first print shows the URL as is. Trying to GET that URL leads to a 400. The second print properly handles it by adding .standardized to the URL. This leads to a 200. The problem is, this only works for the top level/initial manifest, it doesn't work for all the child manifests and segments.
let url = URL(string: "website.com/segmentfolder/../../abc1234/videosegment.mp4")!
let task = URLSession.shared.dataTask(with: url.standardized) {(data, response, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
So question, does AVPlayer support relative URLs? If so, why can't it handle the ../../ in the URL path like other players and curl can? Is there a special way to get it to trigger standardizing ALL URL requests?
Any help would be appreciated.

Sending an excel to frontend - Angular 2, Java

I have a Java API endpoint that returns an excel (I am using content-disposition=Content-Disposition","attachment; filename=Audit.Report.xlsx).
I have another Angular-Node JS application that needs to consume this API and when the user clicks on a link, it should pull the excel and display a pop-up asking them the location to save the document. I am at a loss as to how I can do this. I tried doing the following on the server side though,
Server Code:
getAuditReport = function ( req, resp ) {
var numberOfMonths = req.query.numberOfMonths;
console.log('In first method ' + numberOfMonths);
var auditReportPromise = this.getAuditReportXlPromise ( numberOfMonths );
auditReportPromise.then ( function ( data ) {
resp.headers('Content-Disposition: attachment; filename="audit.report_'+ new Date() + '".xls"');
resp.ContentType = "application/vnd.ms-excel";
resp.status ( 200 ).send ( data );
} ).catch ( function ( err ) {
resp.status ( 500 ).send ( err );
} );
}
The getAuditReportXlPromise method returns a promise to invoke the get method of the Java API. On invoking this API via a browser, I get the excel content on the browser rather than a prompt requesting me to save the document somewhere.
Can someone suggest what's wrong here, and what I need to do on the client side for the click functionality to work.
Update 1:
Following is the code from the HTML
<a id='10051' href="{{url}}" target=_blank class="ok-white-text">
Download Report
</a>
Based on the duration the user selects, I'm building the URL - this is getting built correctly.
If your API provides the file using GET then you should be able to download the file in a simple way by just setting a link to that API (i.e. an anchor containing the link like Download).
In this scenario the browser will take over the download process (i.e. locating the folder to download to, if configured to do so).
If you want to process the file on client side, then you need to transfer it in a binary mode as suggested by multiple answer for this question.
To answer how I did manage to get around this,
Client Side:
In the component, I did the following - wrote a method on clicking the button that contains a window.open to the url - something like,
window.open("<path to the java api>", '_blank');
The link like I mentioned above was a java api that was already generating the excel file.

Dart redstone web application

Let's say I configure redstone as follows
#app.Route("/raw/user/:id", methods: const [app.GET])
getRawUser(int id) => json_about_user_id;
When I run the server and go to /raw/user/10 I get raw json data in a form of a string.
Now I would like to be able to go to, say, /user/10 and get a nice representation of this json I get from /raw/user/10.
Solutions that come to my mind are as follows:
First
create web/user/user.html and web/user/user.dart, configure the latter to run when index.html is accessed
in user.dart monitor query parameters (user.dart?id=10), make appropriate requests and present everything in user.html, i.e.
var uri = Uri.parse( window.location.href );
String id = uri.queryParameters['id'];
new HttpRequest().getString(new Uri.http(SERVER,'/raw/user/${id}').toString() ).then( presentation )
A downside of this solution is that I do not achieve /user/10-like urls at all.
Another way is to additionally configure redstone as follows:
#app.Route("/user/:id", methods: const [app.GET])
getUser(int id) => app.redirect('/person/index.html?id=${id}');
in this case at least urls like "/user/10" are allowed, but this simply does not work.
How would I do that correctly? Example of a web app on redstone's git is, to my mind, cryptic and involved.
I am not sure whether this have to be explained with connection to redstone or dart only, but I cannot find anything related.
I guess you are trying to generate html files in the server with a template engine. Redstone was designed to mainly build services, so it doesn't have a built-in template engine, but you can use any engine available on pub, such as mustache. Although, if you use Polymer, AngularDart or other frameowrk which implements a client-side template system, you don't need to generate html files in the server.
Moreover, if you want to reuse other services, you can just call them directly, for example:
#app.Route("/raw/user/:id")
getRawUser(int id) => json_about_user_id;
#app.Route("/user/:id")
getUser(int id) {
var json = getRawUser();
...
}
Redstone v0.6 (still in alpha) also includes a new foward() function, which you can use to dispatch a request internally, although, the response is received as a shelf.Response object, so you have to read it:
#app.Route("/user/:id")
getUser(int id) async {
var resp = await chain.forward("/raw/user/$id");
var json = await resp.readAsString();
...
}
Edit:
To serve static files, like html files and dart scripts which are executed in the browser, you can use the shelf_static middleware. See here for a complete Redstone + Polymer example (shelf_static is configured in the bin/server.dart file).

Web Api HttpResponseMessage not returning file download

I am currently doing a POST to a Web Api method and am posting an array of objects. When I get to the method, my parameters are resolved properly, and I make a call to the DB and return a list of records.
I then take those records and convert them to a MemoryStream to be downloaded by the browser as an Excel spreasheet. From there, I create an HttpResponseMessage object and set properties so that the browser will recognize this response as a spreadsheet.
public HttpResponseMessage ExportSpreadsheet([FromBody]CustomWrapperClass request){
var result = new HttpResponseMessage();
var recordsFromDB = _service.GetRecords(request);
MemoryStream export = recordsFromDB.ToExcel(); //custom ToExcel() extension method
result.Content = new StreamContent(export);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.Name = "formName";
result.Content.Headers.ContentDisposition.FileName = "test.xlsx";
return result;
}
Instead of seeing the spreadsheet being downloaded, nothing seems to happen. When I check the developer tools (for any browser), I see the Response Headers below while the Response tab just shows binary data. Does anyone know what I might be missing here?
How are you doing your POST? It sounds like you might be trying to this via a javascript AJAX call, which cannot be done (https://stackoverflow.com/a/9970672/405180).
I would instead make this a GET request for starters, and use something like window.location="download.action?para1=value1....". Generally web api Post requests are made to create a file/entry, not retrieve one.
Alternatively, you could use a HTML Form with hidden elements corresponding to your query parameters, and use javascript to submit the form.

Monotouch/iPhone - Call to HttpWebRequest.GetRequestStream() connects to server when HTTP Method is DELETE

My Scenario:
I am using Monotouch for iOS to create an iPhone app. I am calling ASP.NEt MVC 4 Web API based http services to login/log off. For Login, i use the POST webmethod and all's well. For Logoff, i am calling the Delete web method. I want to pass JSON data (serialized complex data) to the Delete call. If i pass simple data like a single string parameter as part of the URL itself, then all's well i.e. Delete does work! In order to pass the complex Json Data, here's my call (i have adjusted code to make it simple by showing just one parameter - UserName being sent via JSON):
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost/module/api/session/");
req.ContentType = "application/json";
req.CookieContainer = jar;
req.Method = "Delete";
using (var streamWrite = new StreamWriter(req.GetRequestStream()))
{
string jSON = "{\"UserName\":\"" + "someone" + "\"}";
streamWrite.Write(jSON);
streamWrite.Close();
}
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
on the server, the Delete method looks has this definition:
public void Delete(Credentials user)
where Credentials is a complex type.
Now, here's the issue!
The above code, gets into the Delete method on the server as soon as it hits:
req.GetRequestStream()
And hence the parameter sent to the Delete method ends up being null
And here's the weird part:
If i use the exact same code using a test VS 2010 windows application, even the above code works...i.e it does not call Delete until req.GetResponse() is called! And in this scenario, the parameter to the Delete method is a valid object!
QUESTION
Any ideas or Is this a bug with Monotouch, if so, any workaround?
NOTE:
if i change the Delete definition to public void Delete(string userName)
and instead of json, if i pass the parameter as part of the url itself, all's well. But like i said this is just a simplified example to illustrate my issue. Any help is appreciated!!!
This seems to be ill-defined. See this question for more details: Is an entity body allowed for an HTTP DELETE request?
In general MonoTouch (based on Mono) will try to be feature/bug compatible with the Microsoft .NET framework to ease code portability between platforms.
IOW if MS.NET ignores the body of a DELETE method then so will MonoTouch. If the behaviour differs then a bug report should be filled at http://bugzilla.xamarin.com

Resources