JQuery handles the response of blob type

In a ASP.NET Core MVC In the controller , According to the condition , May return a Excel File stream for , It is also possible to return a Json Error messages for , The code is similar to :

if(templeteId == null)
{
return Json(new {success = false, msg = " No template specified "});
}
else
{
// Code for generating file stream is omitted ,stream Is a file stream ,fileName File name
return File(stream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{fileName}.xlsx");
}

On the front end , I use jquery Of ajax Access background

$.ajax({
url: "@Url.Action("GenerateReport")",
data: {taskId: taskId, linePointId: linePointId},
dataType: "blob",
type: "get",
success: (result,status,xhr) => {
console.log(result)
},
error: (xhr,status,error) => {
console.log(error)
}
})

Whether it’s back json Or file stream , The console output is No conversion from text to blob.
I thought it was my backstage problem , I even returned Json The code is changed to this :

var json = "{\"success\": false, \"msg\": \" No template file \"}";
return File(Encoding.UTF8.GetBytes(json), "text/plain");

The result is the same .
I put… In the front-end code dataType: "blob" Delete , Call is no problem , But whether it’s a file stream or json, The form of return has become Text.
I am here ajax Functional success Print in callback xhr object , Only then discovered jquery Encapsulated this xhr object , Provided only responseText attribute , And the original XMLHttpRequest Medium response Properties are not provided to us .
Baidu for a while , I found that the successful online processing of my background return type is used axios, But I don’t want to because of a ajax The call to introduces another js library .
Finally, it can only be used XMLHttpRequest Object complete .

function exportReport(taskId, linePointId){
var xhr = new XMLHttpRequest();
xhr.open("get", `@Url.Action("GenerateReport")?taskId=${taskId}&linePointId=${linePointId}`, true);
xhr.responseType = "blob";
xhr.onreadystatechange = () => {
if(xhr.readyState == 4 && xhr.status == 200) {
let contentType = xhr.getResponseHeader("content-type");
let blob = new Blob([xhr.response]);
if(contentType.includes("application/json")) {
blob.text().then(text => {
let json = JSON.parse(text);
layer.msg(json.msg);
});
} else {
let disposition = xhr.getResponseHeader("content-disposition");
let fileName;
if(disposition.includes("filename*")) {
// If you include filename*, Then take the contents of this field as the file name , And decode the file name
fileName = disposition.split(';')[2].split('=')[1];
fileName = fileName.substring(fileName.lastIndexOf("'") + 1);
fileName = urlDecode(fileName);
} else {
fileName = disposition.split(';')[1].split('=')[1];
}
let url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
}
}
xhr.send();
}

Read more here: Source link