使用 fetch 时无法获取 ReadableStream
Cannot get ReadableStream when using fetch
我开始开发基于 Web API / ReactJS 的新 Web 应用程序,我有 api 具有以下签名的方法:
[HttpGet("{clientid}/download/{filename}")]
public async Task<HttpResponseMessage> DownloadFileAsync([FromRoute] int clientid, [FromRoute] string filename)
在 ReactJs 方面,我试图通过执行以下 JS 代码从我的 api 获取流:
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();
})
问题是我收到了如下所示的 json 响应,而不是二进制数据。
{
"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
}
更新 1:
我已经像下面这样更改了获取方法,现在只收到部分数据:
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();
})
更新二:
使用 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();
})
我遇到了两个问题,我已经修复了我的 javascript,如下所示:
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();
})
并且我已经将 api 侧从:
更改为
Task<HttpResponseMessage> to Task<ActionResult<byte[]>>
我的方法的完整代码如下:
[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));
}
我开始开发基于 Web API / ReactJS 的新 Web 应用程序,我有 api 具有以下签名的方法:
[HttpGet("{clientid}/download/{filename}")]
public async Task<HttpResponseMessage> DownloadFileAsync([FromRoute] int clientid, [FromRoute] string filename)
在 ReactJs 方面,我试图通过执行以下 JS 代码从我的 api 获取流:
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();
})
问题是我收到了如下所示的 json 响应,而不是二进制数据。
{
"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
}
更新 1:
我已经像下面这样更改了获取方法,现在只收到部分数据:
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();
})
更新二:
使用 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();
})
我遇到了两个问题,我已经修复了我的 javascript,如下所示:
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();
})
并且我已经将 api 侧从:
更改为 Task<HttpResponseMessage> to Task<ActionResult<byte[]>>
我的方法的完整代码如下:
[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));
}