0

I'm passing an Id on click of a button(button is in 192.xxx.x.xxx\Profile\Details page) to angularJS controller file where it is calling an API

$scope.docView = function () {     
    Method.getbyId("api call",docId).then(function(response) {
            if (response.data.message != null)
                window.open('//'+response.data.message);
            else
                alert("File Not Found !");
        }).catch(function (data) {
            console.log("Unknown Error");
        });
    }
}

API is :

    [Route("api call")]
    [HttpGet]
    public IHttpActionResult ViewDocument (Guid? docId)
    {
          /*background work*/            

                response.Message = filePath;
            }                
        }
        catch (Exception ex)
        {
            Utils.Write(ex);
        }

        return Ok(response);
    }

In response.data.message, the path of the file(192.xxx.x.xxx\folder\filename) on the server is coming which will open the file via window.open(). But in URL, whole path of the folder is visible which will become security breach. Hence I want to 'display the file in a new View' in the same controller which will open the file in a new tab. The url should be like (192.xxx.x.xxx\Profile\Details? docid=xxxxxxxxxxxxxxxxx ).

Marco
  • 22,856
  • 9
  • 75
  • 124
Shalini Raj
  • 177
  • 2
  • 19
  • What is the significance of `c#` tag?? – sujith karivelil Mar 01 '18 at 08:35
  • If you don't want the file to be accessible directly, don't place it in a location where there is a URL to it. Even if you don't directly give it away, it can be indexed by anyone scanning the site, so it already has no security. So move it to an offline location, make a database entry for each file with an ID, and in your view use the file ID as the parameter, and in the background code you look up the ID in the database, find the related file on disk, extract its content and send it for download like an attachment (you can google examples of that). – ADyson Mar 01 '18 at 09:17
  • @ADyson sorry I dint get to know properly what you meant by saving id , extract content. – Shalini Raj Mar 01 '18 at 09:52
  • @ADyson The problem is I should not download the file, it should just popup in a new tab in the browser BUT not with the file path as URL. – Shalini Raj Mar 01 '18 at 09:55
  • "The problem is I should not download the file, it should just popup in a new tab in the browser "...yes you can open a new tab but whether the file gets embedded in the browser window or downloaded depends whether the user's browser has the ability to display it directly or not. e.g. maybe a HTML or JPG or sometimes a PDF might be displayed within the browser window (due to native support or a plugin like Adobe) other file types will just be downloaded anyway. That part is not fully in your control – ADyson Mar 01 '18 at 09:57
  • Anyway, by file content I mean not the file itself, rather the contents of the file as a stream of bytes. Then you can write that byte array into the response to your API call. There are examples online – ADyson Mar 01 '18 at 09:59
  • In fact I made this one only a couple of days ago: https://stackoverflow.com/a/48987893/5947043 . As you can see a made a useful re-usable class for enabling easy file downloads from Web API – ADyson Mar 01 '18 at 10:00
  • That one I tried but it was using System.Web.MVC and it created error for my other apis which are using HTTP – Shalini Raj Mar 01 '18 at 10:17
  • None of the code in that link I gave you requires System.Web.MVC AFAIK. It's designed for Web API specifically. What gives you the impression it requires MVC? There actually _is_ a FileResult class already in MVC, instead I made a version (with the same class name admittedly) which is designed for use in a Web API controller. Do not confuse this code with the existing MVC FileResult object. – ADyson Mar 01 '18 at 11:18
  • will it be possible to download the file from api call and then store it in temp variable or something in angularJS controller and then view that ? – Shalini Raj Mar 01 '18 at 12:27
  • You can't really download a file via ajax - it can't handle attachments like that. You just need to make a hyperlink to your Download action method's URL, and let the user click on it, or open a new window using Javascript which goes to that URL. If you changed the web API to just output a base64-encoded string version of the file content, you could download _that_ via ajax as it's just text and not a file...but then what would you do with it anyway? There's no built-in way for the browser to display most file types, and certainly not using Javascript. – ADyson Mar 01 '18 at 13:30
  • I've just noticed I linked you back to a question _you_ asked...where I'd already explained you couldn't download a file via ajax. – ADyson Mar 02 '18 at 09:11

1 Answers1

1

What you are actually looking for, you can find with a quick search on Google: "Download file from an ASP.NET Web API method".

For example here and here you'll find examples which implement what you are looking for.

EDIT:

HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(result);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(System.Net.Mime.DispositionTypeNames.Inline)
{
    FileName = "foo.pdf"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

As derived from this and this Thread.

You would need to change the Content-Type according to the actual file type. Also if the file is actually viewable inside the Browser depends on wether the Browser is able to do so.

Severin Jaeschke
  • 661
  • 7
  • 22
  • The problem is I should not download the file, it should just popup in a new tab in the browser BUT not with the file path as URL. BTW thank you for your suggestion. – Shalini Raj Mar 01 '18 at 09:39
  • From Example 1 you'll be able to derive the Controller and Method. Then you'll need to set the proper headers so your browser trys to open the file instead of downloading: [link](https://stackoverflow.com/questions/47730249/open-generated-pdf-file-in-new-tab-instead-of-downloading-web-api) – Severin Jaeschke Mar 01 '18 at 09:59
  • I still am not able to know what to write in place of window.open('//'+response.data.message); in angularJS controller file – Shalini Raj Mar 01 '18 at 10:48
  • 1
    windown.open('url', '_blank'); 'url' would need to be the path to your controller method through which you want to handle your document downloads with some form of identifier which document is to be send. (for example 'url' + 'id=' + id) – Severin Jaeschke Mar 01 '18 at 10:55
  • url should be apicontroller route or something else? it wont be able to call api right ?. sorry I'm really new to webapi. – Shalini Raj Mar 01 '18 at 11:07
  • 1
    No you're getting there. Url is according to the Route you specified for your api (Default would be "api/{controller}/{id}") So you would need to reference the controller name and in the get method you implement the above code which will need to be a liitle adjusted according to your needs. In Web Api 2 you can also do the routing specific to the action. If you are unsure you can read up on that [here](https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/) – Severin Jaeschke Mar 01 '18 at 11:16
  • will it be possible to download the file from api call and then store it in temp variable or something in angularJS controller and then view that ? – Shalini Raj Mar 01 '18 at 12:27
  • It would likely be possible. But you would need to generate the view yourself. Depending on the file and its markup that can be hard. So in general yes, but depending on practicality it would not be wise to do so. You should research on the webs on that notion and maybe open a new question if need be. – Severin Jaeschke Mar 01 '18 at 12:50