I am trying to download a file using web API + Angularjs and it's working fine, however I'm sending 'content-disposition' in the header from the web API but I'm unable to access it in the response-header.
WebAPI:
[HttpGet]
[AllowCrossSiteJson]
public HttpResponseMessage GetAcquisitionsTemplate()
{
var docContent = _d.FirstOrDefault();
Stream stream = new MemoryStream(docContent.Content);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
string contentDisposition = string.Concat("attachment; filename=", docContent.Name.Replace(" ", String.Empty), "." + docContent.Extension);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse(contentDisposition);
return result;
}
Client Side (AngularJs):
$http.get(url)success(function (data, status, headers) {
var header= headers();
})
In the header I'm getting the following values but I'm unable to get content-disposition. Please correct me where I'm wrong?
I guess you are trying to hit it from localhost while the file is hosted on the server, in that case ask your server team to allow , Access-Control-Expose-Headers(‘Content-Disposition’) . With this Header, custom headers like COntent-Disposition will be accessible to you over cross domain
Related
I am trying to retrieve a document from a document warehouse then display that document in a new browser tab. I am using .net core 3.1 and react 16.
Here's what i have tried:
var link = '/Document/ViewDocument?docId=' + docId
window.open(link, "_blank");
This give an Unsupported media type error 415 and the request never hits the controller.
I tried using fetch and returning a filepath but this is restricted in the browser.
const response = await fetch('Document/ViewDocument', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ docId: docID })
});
const data = await response.json();
window.open('file:///' + data, "_blank"); //data = filepath
I've also tried fetch and returned a file from the controller but this didn't work either"
Here is my controller method:
[HttpGet]
[Route("ViewDocument")]
public async Task<IActionResult> ViewDocument(int docId)
{
//There is logic omitted here that actually retrieves the document from the document warehouse by docId.
string filePath = "C:\\inetpub\\wwwroot\\app\\tempfiles\\fileName";
string contentType = "application/pdf";
FileStream fs = new FileStream(filePath, FileMode.Open);
return File(fs, contentType);
}
In .net 4.7 i was able to do this:
var link = '#Url.Action("ViewDocument", "Document", new { area = "" })?docId=' + docId;
window.open(link, "_blank");
Can someone please help me figure out how to return a file from the controller and display that file in a new browser tab?
This actually does work:
var link = '/Document/ViewDocument?docId=' + docId
window.open(link, "_blank");
It didn't appear to be working initially because there was an error occuring in the document warehouse api.
I'm working on download feature. When I run code on localhost, it runs perfectly without any error. But when I uploads same code to server then it returns Failed to load resource: the server responded with a status of 400 (Bad Request) error in console of browser. For requesting and getting response from server, I have used Axios. I'm newbie to ASP.NET Core + ReactJS technology stack and working on APIs for the first time so it's being difficult for me to figuring out root cause of this error.
Here is my code for requesting data from server.
axios({
method: 'POST',
url: '/api/ImageFetch/ImageFetchPoint',
responseType: 'blob',// important
headers: {
'Content-Type': 'application/json'
},
data: filepath
}).then(function(response) {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
}).catch(error => {
console.log("Status:", error.response.status);
console.log("Data:", error.response.data);
});
For getting response as file(any extension) from server, I've used following code.
[HttpPost("PanImageFunction")]
[Route("api/[controller]/[action]")]
public async Task<IActionResult> ImageFetchFunction([FromBody] ImageFetchRequest request)
{
var filePath = request.ImagePath;
var filename = System.IO.Path.GetFileName(filePath);
string path="unknownpath";
try {
if (filename == null)
return Content("filename not present");
path = Path.Combine(
Directory.GetCurrentDirectory(),
"RegistrationImages", filename);
} catch(Exception ex) {
new Logger().write(ex);
}
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = false // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add("Content-Type", "multipart/form-data");
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
private string GetContentType(string path)
{
var types = GetMimeTypes();
var ext = Path.GetExtension(path).ToLowerInvariant();
return types[ext];
}
private Dictionary<string, string> GetMimeTypes()
{
return new Dictionary<string, string>
{
{".txt", "text/plain"},
{".pdf", "application/pdf"},
{".doc", "application/vnd.ms-word"},
{".docx", "application/vnd.ms-word"},
{".xls", "application/vnd.ms-excel"},
{".png", "image/png"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".gif", "image/gif"},
{".csv", "text/csv"}
};
}
Complete code works perfectly on localhost. But when I uploads it on server then it throws 400 bad request error on console of browser as you can see in following image.
I have checked many forums and articles but most of the articles related to ASP.NET core giving solution related to Razor pages and not giving solutions related to ReactJS and Axios.
How can I fix this error?
I am new to Microsoft graph so this might be a dumb question.
So I am writing a command line application trying to update a page in our team onenote. (enterprise onenote)
Here is the code I got work getting the token.
https://login.microsoftonline.com/common/oauth2/authorize?client_id=my_client_Id&response_type=code&redirect_uri=Some_uri&resource=https://graph.microsoft.com&scope=Notes.ReadWrite.All
I got the token as strCode and trying to retrieve all the notes under this account by these codes:
var baseAddress = new Uri("https://graph.microsoft.com/v1.0/me/onenote");
using (var httpClient = new HttpClient { BaseAddress = baseAddress })
{
var request = new HttpRequestMessage(HttpMethod.Get, #"/pages");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", strCode);
using (var response = httpClient.SendAsync(request).Result)
{
string responseData = response.Content.ReadAsStringAsync().Result;
}
}
And in the response data I got
"{ \"error\": { \"code\": \"InvalidAuthenticationToken\", \"message\": \"CompactToken parsing failed with error code: -2147184105\", \"innerError\": { \"request-id\": \"*********************", \"date\": \"2017-06-08T18:25:06\" } } }"
Any idea how to fix this..?
Problem resolved .
I need to convert the authentication code into a "real" access token..
The one that I got is not an access token.
I'm trying to download a server generated spreadsheet.
My application uses Angular on the front-end and Java on the back-end.
Here's the method on the back-end that receives the request to generate and return the file:
#RequestMapping(value = "download", method = RequestMethod.GET, produces = "application/xls")
public ResponseEntity<InputStreamResource> download() throws IOException {
ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet worksheet = workbook.createSheet("POI Worksheet");
HSSFRow row1 = worksheet.createRow((short) 0);
HSSFCell cellA1 = row1.createCell((short) 0);
cellA1.setCellValue("Hello!");
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFillForegroundColor(HSSFColor.GOLD.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cellA1.setCellStyle(cellStyle);
workbook.write(fileOut);
fileOut.close();
byte[] file = fileOut.toByteArray();
return ResponseEntity
.ok()
.contentLength(file.length)
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new InputStreamResource(new ByteArrayInputStream(file)));
}
And on the front-end, the following function is executed when the user clicks on Download button:
$scope.exportFile = function() {
$http.get('http://127.0.0.1:8000/api/excel/download')
.success(function (data, status, headers, config) {
var anchor = angular.element('<a/>');
anchor.attr({
href: 'data:application/octet-stream;charset=utf-8,' + encodeURI(data),
target: '_blank',
download: 'spreadsheet.xls'
})[0].click();
})
.error(function (data, status, headers, config) {
// handle error
});
};
The returned spreadsheet contains unreadable characters.
If I access http://127.0.0.1:8000/api/excel/download directly, the spreadsheet is downloaded without the .xls extension (with no extension at all). If I rename the file adding the .xls extension and then open it, I can see the file contents. So I think the problem it's on the call Angular does to back-end and not on generating the file on Java.
Has anyone experienced this situation or have some example to share? What am I doing wrong?
The Content-Disposition header should do the trick. So, you would have something like this:
HttpHeaders headers = new HttpHeaders();
headers.setContentDispositionFormData("Attachment", "spreadsheet.xls");
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(file.length);
return new ResponseEntity<InputStreamResource>(
new InputStreamResource(new ByteArrayInputStream(file)),
headers, HttpStatus.OK);
I have a Dart code used to send an HttpRequest with a POST method to my GAE WepApp2 application. The dart code is executed in chromium and serve by Chrome dev editor. I add in my GAE code some headers to avoid the XHR error in the client side.
The dart code send the datas to my GAE app but I can't read the data with self.request.POST.get("language")) and the app never enter in def post(self): section but with self.request.body I can read the data.
Could you explain that and provide some correction to have a full POST compliant code?
dart:
void _saveData() {
HttpRequest request = new HttpRequest(); // create a new XHR
// add an event handler that is called when the request finishes
request.onReadyStateChange.listen((_) {
if (request.readyState == HttpRequest.DONE &&
(request.status == 200 || request.status == 0)) {
// data saved OK.
print(request.responseText);
}
});
// POST the data to the server
var url = "http://127.0.0.1:8080/savedata";
request.open("POST", url, async: false);
String jsonData = JSON.encode({"language":"dart"});
request.send(jsonData);
}
GAE code in my handler:
def savedata(self):
logging.info("test")
logging.info(self.request.body)
logging.info(self.request.POST.get("language"))
def post(self):
logging.info("test 2")
logging.info(self.request.POST.get("language"))
self.response.headers["Access-Control-Allow-Origin"] = "http://127.0.0.1:49981"
self.response.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
In Dart, if you don't specify request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") in your HttpRequest, the data is considered by GAE like a bite stream and you can only read them with self.request.body
If you add the Content-Type header in Dart you need also to change the data formating. In my case I mimic a form sending with POST method so I change String jsonData = JSON.encode({"language":"dart"}); by String jsonData = "language=dart2";
IN GAE python I can now read the data with self.request.POST.get("language")
If you need to send a JSON from DART to GAE, you can encode the string like this:
String jsonData = JSON.encode({"test":"valuetest1"});
String datas = "datas=$jsonData";
request.send(datas);
In GAE you can read the datas like this:
my_json = json.loads(self.request.POST.get("datas"))
logging.info(my_json["test"])
The complete code:
Dart
void _saveData2() {
String url = "http://127.0.0.1:8080/savedata";
HttpRequest request = new HttpRequest()
..open("POST", url, async: true)
..setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
..responseType = "arraybuffer";
String jsonData = JSON.encode({"test":"valuetest1"});
String datas = "datas=$jsonData";
request.send(datas);
}
GAE
class PageHandler(webapp2.RequestHandler):
def savedata(self):
self.response.headers.add_header('Access-Control-Allow-Origin', '*')
self.response.headers['Content-Type'] = 'application/json'
#logging.info(self.request)
my_json = json.loads(self.request.POST.get("datas"))
logging.info(my_json["test"])