dotent core blob storage caching - c#

I have image processor app, for processing image and getting it from azure blob storage. In this moment my blob storage service is returning absolute url to image of blob return redirect to this url. For example:
[Route("/blob-storage/{imageName}")]
[HttpGet]
public async Task<IActionResult> GetImage(string imageName, ImageSize size)
{
var imageUrl = await this.ImageProcessorFacade.GetImageUrl(imageName, size);
return Redirect(imageUrl);
}
Now I want to caching this returned image. Yes, exists ResponseCache attribute, but It doesn't me work with redirect and I thing that it is bad way to solving this problem. For get image, I call for example this: http://localhost/blob-storage/test.jpeg?size...
And response is redirect to blob.windows.net/... etc.
Is there way, how to cache it?
Thank you for your time!

I want to caching this returned image. Yes, exists ResponseCache attribute, but It doesn't me work with redirect and I thing that it is bad way to solving this problem. For get image, I call for example this: http://localhost/blob-storage/test.jpeg?size... And response is redirect to blob.windows.net/... etc.
You call Redirect() method in your controller action to redirect to a specified URL, the HTTP Location header field will be returned in response. And then the user agent (e.g. a web browser) that is invited by a response with 3xx code will make a second request to the new URL specified in the location field, which happens on web browser side, you could not append or modify cache-related headers to response.
If you'd like to lower latency and faster delivery the images that stored in Azure blob storage, you could try to use the CDN.

Related

ASP.NET Core Response headers on a FileStreamResult

I am doing a .mp4 file download from Azure Blob storage and pushing that to the UI. The download works fine, the issue is it doesn't look like the headers are set correctly for content-length. Thus you cannot track the download time because the browser only says what has been downloaded and not how much is left and the estimated time. Is my code for the response wrong or should I change my request? My code as follows:
[HttpGet("VideoFileDownload")]
public IActionResult VideoFileDownloadAsync([FromQuery]int VideoId)
{
...code to get blob file
return new FileStreamResult(blob.OpenRead(), new MediaTypeHeaderValue("application/octet-stream")
}
I have played around with various request and response headers but it makes no difference.
The files are big and I know the old asp.net way of checking for range headers and then do a chunked stream but I want to use the new features in .net core which doesn't work as expected or maybe I just don't understand it thoroughly. Can somebody give me a working sample of a file download with asp.net core code.
If you have the file size, you can set the response's content length in the Response object just before returning the FileStreamResult, like this:
[HttpGet("VideoFileDownload")]
public IActionResult VideoFileDownloadAsync([FromQuery]int VideoId)
{
...code to get blob file
long myFileSize = blob.Length; // Or wherever it is you can get your file size from.
this.Response.ContentLength = myFileSize;
return new FileStreamResult(blob.OpenRead(), new MediaTypeHeaderValue("application/octet-stream")
}

c# asp.net MVC Download a file via Ajax

I'm pretty sure this isn't possible but I thought I'd ask...
I have a FileResult which returns a file, when it works there's no problem. When there's an error in the FileResult for some reason, I'd like to display an exception error message on the users screen, preferably in a popup.
Can I do an Ajax post which returns a file when successful and displays a message if not?
I think it is not possible cause in order to handle ajax post, you will have to write a javascript handler on the client side and javascript cannot do file IO on client side.
However, what you can do is, make an ajax request to check if file exists and can be downloaded. If, not, respond to that request negatively which will popup a dialog on client side. If successful, make a file download request.
Not specifically related to MVC but...
it can be done using XMLHttpRequest in conjunction with the new HTML5 File System API that allows you to deal with binary data (fetched from http response in your case) and save it to the local file system.
See example here: http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-example-savingimages
Controller (MyApiController) Code:
public ActionResult DownloadFile(String FileUniqueName)
{
var rootPath = Server.MapPath("~/UploadedFiles");
var fileFullPath = System.IO.Path.Combine(rootPath,FileUniqueName);
byte[] fileBytes = System.IO.File.ReadAllBytes(fileFullPath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, "MyDownloadFile");
}
Jquery Code:
$(document).on("click"," a ", function(){ //on click of anchor tag
var funame=$(this).attr('uname'); /*anchor tag attribute "uname" contain file unique name*/
var url = "http://localhost:14211/MyApi/DownloadFile?FileUniqueName= " + funame;
window.open(url);
});

How to ensure a url is called from my application and not manually from browser

I have an application that contains a button, on click of this button, it will open a browser window using a URL with querystring parameters (the url of a page that i am coding).
Is there a way to ensure that the URL is coming from my application and only from my application - and not just anyone typing the URL manually in a webbrowser?
If not, what is the best way to ensure that a specific URL is coming from a specific application - and not just manually entered in the address bar or a web browser-
Im using asp.net.
You can check if the request was made from one of the pages of your application using:
Request.UrlReferrer.Contains("mywebsite.com")
That's the simple way.
The secure way is to put a cookie on the client containing a value encrypted using a secure key or hashed using a secure salt. If the cookie is set to expire when the page is closed it should be impossible for someone to forge.
Here's an example:
On the pages that would redirect to the page you are trying to protect:
HttpCookie cookie = new HttpCookie("SecureCheck");
//don't set the cookie's expiration so it's deleted when the browser is closed
cookie.Value = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Session.SessionID, "SHA1");
Response.Cookies.Add(cookie);
On the page you are trying to protect:
//check to see if the cookie is there and it has the correct value
if (string.IsNullOrEmpty(Request.Cookies["SecureCheck"]) || System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Session.SessionID, "SHA1") != Request.Cookies["SecureCheck"])
throw Exception("Invalid request. Please access this page only from the application.");
//if we got this far the exception was not thrown and we are safe to continue
//insert whatever code here
There's no reliable way to do this for a GET request, nor is their any reason to try for a legitimate user. What you should do instead is ensure that regardless of where the request comes from the user has the proper permissions and access rights and that the session is protected appropriately (HTTP only cookies, SSL, etc.) If the request is changing data, then it should be a POST, not a GET, and it should be accompanied by some suitable cross-site request forgery prevention techniques (such as a cookie containing a nonce that is verified against a matching nonce on the form itself).
There is no way, other than rejecting the request if it doesn't contain a previously generated random one-time token in the parameters (that would be stored in the session, for example).
While there is no 100% secure way to do this, what I am suggesting might at least take care of your basic needs.
This is what you can do .
Client: Add a HTTP header with an encoded string that is like hash (sha256) of some word.
Then make your client always do a POST request instead of GET.
Server: Check the HTTP Header for encoded string. Also make sure it is a POST request.
This is not 100% as ofcourse someone smart enough could figure out and still generate a request, but depending on your need you might find this enough or not
You can check the referer, the user agent, add an additional header to the request, always do post requests to that url. However, considering HTTP is transmitted in plain text, somebody is always able to let wireshark or fiddler run, capture the HTTP packets and recreate the requests with your measures in place.
Pass parameters from your application so that you can verify on the server side.
I suggest you use an encryption algorithm and generate random text using a password(key). Then, decrypt the param on the server side and check if it matches your expectation.
I am not very clear though. sorry about that, If had to do something like this, then, I would do something similar to mentioned above.
You can use to check the header on MVC controller like Request.Headers["Accept"]; if it is coming from your code in angularjs or jquery:
sample angularjs like this:
var url = ServiceServerPath + urlSearchService + '/SearchCustomer?input=' + $scope.strInput;
$http({
method: 'GET',
url: url,
headers: {
'Content-Type': 'application/json'
},.....
And on the MVC [HttpGet] Action method
[HttpGet]
[PreventDirectAccess]//It is my custom filters
// ---> /Index/SearchCustomer?input={input}/
public string SearchCustomer(string input)
{
try
{
var isJsonRequestOnMVC = Request.Headers["Accept"];//TODO: This will check if the request comes from MVC else comes from Browser
if (!isJsonRequestOnMVC.Contains("application/json")) return "Error Request on server!";
var serialize = new JavaScriptSerializer();
ISearch customer = new SearchCustomer();
IEnumerable<ContactInfoResult> returnSearch = customer.GetCustomerDynamic(input);
return serialize.Serialize(returnSearch);
}
catch (Exception err)
{
throw;
}
}

How is an image served from a URL with an ASPX extension?

Can Somebody tell how to create such kind of urls
for example if you see the url
http://office.microsoft.com/global/images/default.aspx?assetid=ZA103873861033
you will redirect to an image ..
my question is , though this url is an image..its extension is aspx..how is it possible.
how to create such kind of url's
Thanks
This is a common method for displaying an image that's stored as a binary object in a database. One tutorial, among many, can be found here.
Essentially, what they're doing is using the aspx page to accept the URL parameter which tells them what image to fetch from the database. Then in the response they clear all output and headers, set the headers for the image, write the binary data to the response stream, and close the response stream.
So it's not really "redirecting" you to an image. The "page" being requested turns out to be an image resource in the response.
By setting the ContentType in the response from the server
HttpContext.Response.ContentType = "image/jpeg";
easiest way is to add generic handler *.ashx and in ashx file u'll have code behind which u can get querystring and manipulate response eg. Response.WriteFile(...)
File extensions literally have no meaning on the WWW. The thing that correctly describes the content at a particular URL is the content-type/MIME-type. This is delivered in an HTTP header when the URL is requested prior to delivery of the main HTTP payload. Other answers describe how you might correctly set this in ASP.NET.
Aside from all other answers they may be doing a Server.Transfer() (so that you don't see it client-side) to the image file. This still means the response headers are being set to the appropriate MIME type but it also means the image isn't necesarilly coming from a database. This technique can be used to hide the actual image URL in attempts to prevent hotlinking.

Writing a stream to the response in ASP.Net

Ok just want to clarify something with my solution.
I have a requirement to grab a file from a respository somewhere, this repository requires a session token to be passed in the form of a cookie along with the request for the file.
I am authenticating the user against this repository and storing the session token in the users cookie collection for my application when the user first logs onto my application.
Problem is the cookie will not get sent to the repository when a user tried to access a file because the repository is on a different URL and domain. Therefore I am creating a new http request, appending the cookie and getting the response stream back.
I now need to send this response stream back to the user, headers and all (as this response stream will contain the headers for the file the user is trying to access)
Can I use this:
string session = cookie.Value;
StreamReader reader = new StreamReader(Utility.GetLinkStream(url, session));
Context.Response.ClearHeaders();
Context.Response.Clear();
Context.Response.Write(reader.ReadToEnd());
Essentially the call to Utility.GetLinkStream goes off and creates a http request then returns the stream of the response. Will the call to Write write out the whole response headers and all, or is there a better way to acheive this?
Response.Write() will only write content, you have to set the headers before calling this. You could enumerate the headers from the WebResponse and add them to the Response.Headers manually.

Categories

Resources