I know this is old but since this pointed me in the right direction, I thought I would share what I am doing in case someone else lands here. I am not using Angular btw.
The user can view or download the file. The choice is given with 2 buttons or 2 links
<button type="button" class="btn btn-primary btn-sm show_tooltip download-form" title="Download File" data-formid="{{ @your-id }}" data-forcedownload="1">
    <i class="fas fa-file-download"></i>
</button>
<button type="button" class="btn btn-primary btn-sm show_tooltip download-form" title="View File" data-formid="{{ @your-id }}" data-forcedownload="0">
    <i class="fas fa-search"></i>
</button>
I am using jQuery with the native plugin for xhr2. This handles the link/buttons
$('.download-form').click(function(event) {
    event.preventDefault();
    let fid = $(this).data('formid');
    let force_download = $(this).data('forcedownload');
    $.ajax({
          url: '/download',
          dataType: 'native',
          type: 'POST',
          xhrFields: {
              responseType: 'blob'
          },
          data: {
               //you can send any parameters via POST here
               personID: "{{ @personID }}",
               file_record_id: pfid,
               file_type: "contract_form",
               dept: "your-dept",
               file_category: "fcategory",
               force_download: force_download
           },
           success: function(blob, status, xhr){
                if (xhr.getResponseHeader('Custom-FileError')>1) {
                      alertify.error(xhr.getResponseHeader('Custom-ErrorMsg'));
                }else{
                      //I thought this would work when viewing the PDF but it does not.
                      blob.name = xhr.getResponseHeader('Custom-FileName');
                      var fileURL = URL.createObjectURL(blob);
                      if (xhr.getResponseHeader('Custom-ForceDownload')==1) {
                            window.open(fileURL);
                            var link=document.createElement('a');
                            link.href=window.URL.createObjectURL(blob);
                            link.download=xhr.getResponseHeader('Custom-FileName');
                            link.click();
                       }else{
                            file_modal(fileURL,'Any Title');
                       }
                       
                   }
              }
           })
});
Then, some more javascript for the modal
function file_modal(blob,the_title)
{
    let spinner = "<div class='text-center'><i class='fa fa-spinner fa-spin fa-5x fa-fw'></i></div>";
    $("#modal_static_label").html('Loading');
    $("#modal_static .modal-body").html(spinner);
    if (blob.length > 1) {
        $("#modal_static").modal("show");
        $("#modal_static_label").html(the_title);
        $("#modal_static .modal-body").empty().append('<iframe src='+blob+' width="100%" height="500px" style="border:none;"></iframe>');
    }else{
         $("#modal_static .modal-body").empty().html('File error');
    }
    $("#modal_static .modal-footer").html('<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>');
        
}
On the server side you will need to send custom headers like this [PHP]
header("Content-length: $file_size");
header("Custom-FileError: 0");
header("Custom-FileName: ".$this->params['original_filename']);
header("Custom-ForceDownload: ".$this->params['force_download']);
header('Content-Type: '.$web->mime($this->full_path.$this->new_file_name));
readfile($this->full_path.$this->new_file_name);
If the user clicks "view", a modal will display the PDF if they click "download", the download window will show up with the filename of your choosing. I have tested this with PDF files less than 10mb and it works as expected.
I hope someone finds this useful.