javascript - Cannot get ReadableStream when using fetch
问题描述
I started developping new web application based on Web API / ReactJS, I have api method with the following signature:
[HttpGet("{clientid}/download/{filename}")]
public async Task<HttpResponseMessage> DownloadFileAsync([FromRoute] int clientid, [FromRoute] string filename)
In the ReactJs side i trying to get a stream from my api by doing the following JS code:
await fetch(`someservice/${clientid}/download/${fileName}`, { responseType: "arraybuffer" })
.then(function (res) {
var response = res;
return response.body;
})
.then(function (blob) {
// Create an object URL for the blob object
const url = URL.createObjectURL(blob);
console.log(url);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = fileName || 'download';
a.click();
})
The issue is that i'm recieving a json response like below instead of binary data.
{
"version":{
"major":1,
"minor":1,
"build":-1,
"revision":-1,
"majorRevision":-1,
"minorRevision":-1
},
"content":{
"headers":[
{
"Key":"Content-Type",
"Value":[
"application/octet-stream"
]
},
{
"Key":"Content-Length",
"Value":[
"119503316"
]
}
]
},
"statusCode":200,
"reasonPhrase":"OK",
"headers":[
],
"trailingHeaders":[
],
"requestMessage":null,
"isSuccessStatusCode":true
}
Update 1:
I have changed the fetch method like below and now recieve only partial data:
await fetch(`someservice/${clientid}/download/${fileName}`)
.then(function (res) {
var response = res;
return response.body;
})
.then(function (body) {
var reader = body.getReader()
var result;
var charsReceived = 0;
reader.read().then(function process({ done, value }) {
if (done) {
console.log("Stream complete");
return;
}
// value for fetch streams is a Uint8Array
const chunk = value;
charsReceived += value.length;
console.log(charsReceived);
result += chunk;
// Read some more, and call this function again
return reader.read().then(process);
});
return result;
})
.then(function (blob) {
// Create an object URL for the blob object
const url = URL.createObjectURL(blob);
console.log(url);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = fileName || 'download';
a.click();
})
Update 2:
Still have same partial data recieved event after using of arrayBuffer
await fetch(`someservice/${clientid}/download/${fileName}`)
.then(function (res) {
var response = res;
return response.arrayBuffer();
})
.then(function (blob) {
console.log(blob);
// Create an object URL for the blob object
const url = URL.createObjectURL(blob);
console.log(url);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = fileName || 'download';
a.click();
})
解决方案
I had two issues and I have fixed my javascript like below:
await fetch(`lynxdumper/${clientid}/download/${fileName}`, { responseType: "blob" })
.then((response) => {
return response.blob();
})
.then(function (file) {
console.log(file);
let blob = new Blob([file], { type: 'dmp' });
console.log(blob);
// Create an object URL for the blob object
const url = URL.createObjectURL(blob);
console.log(url);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = fileName || 'download';
a.click();
})
And I have changed the api side from:
Task<HttpResponseMessage> to Task<ActionResult<byte[]>>
The full code of my method is below:
[HttpGet("{clientid}/download/{filename}")]
public async Task<IActionResult> DownloadDumpFileAsync([FromRoute] int clientid, [FromRoute] string filename)
{
var client = clientRepository.GetClientById(clientid);
var channel = GrpcChannel.ForAddress(client.BaseUrl.AbsoluteUri, new GrpcChannelOptions
{
HttpClient = CreateHttpClient(),
MaxReceiveMessageSize = 1024 * 1024 * 1024,
MaxSendMessageSize = 1024 * 1024 * 1024
});
var serviceclient = new DumperService.DumperServiceClient(channel);
var replay = await serviceclient.DownloadAsync(new DowloadRequest { Filename = filename });
var bytes = replay.Chunk.ToByteArray();
return Ok(new MemoryStream(bytes));
}
推荐阅读
- java - Format amount in Canadian for finance area
- postgresql - Oracle unpivot multiple columns equivalent in Postgres
- docker - GRPC service working fine running locally, but failing to connect when run from a Docker container - How to debug?
- arrays - How can I transform a numeric Scala array to be an array of intervals of the values from array?
- javascript - 如何获取 primeNg 数据表分页器页面值和搜索过滤器值?
- python - 如何从 tkinter 中的函数获取组合框的值
- python - 根据上一行的最新值更新行值
- javascript - Jquery - 选择具有特定类的所有元素并根据数据属性更改文本
- javascript - 当我导航到本机反应的另一个屏幕时,状态变为空
- python-3.x - 为什么工作完成后不能加入流程?