使用 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));
    }