Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpClient enhancements - binary data #16257

Closed
SvenEV opened this issue Apr 3, 2018 · 14 comments
Closed

HttpClient enhancements - binary data #16257

SvenEV opened this issue Apr 3, 2018 · 14 comments
Labels
area-blazor Includes: Blazor, Razor Components

Comments

@SvenEV
Copy link

SvenEV commented Apr 3, 2018

Currently HttpClient cannot be used to retrieve binary data such as images. The response content appears to get truncated at zero bytes when the HTTP response is returned from JS back to .NET. In some cases, requests just fails with "SCRIPT7017: Memory index is out of range" (Edge) or "RuntimeError: memory access out of bounds" (Chrome) without anything being returned.

I found a TODO regarding this issue in the code (see below). Anyway, I think this should be tracked and I hope this isn't a duplicate.

https://github.com/aspnet/Blazor/blob/a9c45fe78ac18b6bd524904b40896c249f9f09c0/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Services/Http.ts#L32-L47

@SteveSandersonMS SteveSandersonMS changed the title Cannot retrieve binary data with HttpClient HttpClient enhancements Apr 4, 2018
@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Apr 4, 2018

Thanks @SvenEV - it's good to have an issue to track this. So, starting a list of possible future enhancements:

@rockfordlhotka
Copy link

Also byte arrays. I ran into this last night, and changed my code to base64 encode the data, but it would be more efficient to just pass the binary byte array like on other platforms.

@aguacongas
Copy link
Contributor

Upload/Download progression events

@yowl
Copy link

yowl commented May 3, 2018

And consuming Content-Type: application/msbin1 web services would be helpful for large data transfer apps.

@RemiBou
Copy link
Contributor

RemiBou commented May 4, 2018

  • different model depending on response code (bad request won't send the same paylone as ok)

Don't know if it's in the scope of this issue

SteveSandersonMS referenced this issue in dotnet/blazor May 23, 2018
#815)

* Add support for zero copy byte array marshalling

* Add support for sending arbitrary HttpContent, refs #479

* Fix unit test to set ContentType correctly

* Add support for receiving binary data

* Compare header case insensitive

* Add unit test for binary http requests
@SteveSandersonMS
Copy link
Member

@rockfordlhotka byte[] is now handled for both sending and receiving thanks to dotnet/blazor#815

@danroth27 danroth27 changed the title HttpClient enhancements HttpClient enhancements - binary data Jun 7, 2018
SteveSandersonMS referenced this issue in SteveSandersonMS/BlazorMigration Nov 27, 2018
dotnet#815)

* Add support for zero copy byte array marshalling

* Add support for sending arbitrary HttpContent, refs #479

* Fix unit test to set ContentType correctly

* Add support for receiving binary data

* Compare header case insensitive

* Add unit test for binary http requests
@gojanpaolo
Copy link

gojanpaolo commented Jun 5, 2019

Hello, I would just like to ask if someone could provide an example on how to use this feature to upload files from the client and send it to the server? I'm completely new to web development so any help would be greatly appreciated. Thanks!

On client-side I have

<input type="file" onchange="@UploadFile" id="fileUpload" />
@functions {
    private void UploadFile()
    {
      // what to do here?
    }
}

On server-side, I think it's something like this

[HttpPost("upload")]
public async Task<IActionResult> Upload(List<IFormFile> files)
{
    // or var files = Request.Form.Files;
    // process files here
}

@smartprogrammer93
Copy link

@gojanpaolo
An easy google search would lead you to this.

https://remibou.github.io/Upload-file-with-Blazor/
Try it out and let me know if you need help

@gojanpaolo
Copy link

gojanpaolo commented Jun 5, 2019

@smartprogrammer93 yes I found that. But it needs JS Interop. I thought this merged PR solved not having to use JS Interop during file upload?

giving it a try..
index.html

<body>
    <app>Loading...</app>

    <script src="_framework/blazor.webassembly.js"></script>
    <script>
        window.readUploadedFileAsText = (inputFile) => {
            const temporaryFileReader = new FileReader();
            return new Promise((resolve, reject) => {
                temporaryFileReader.onerror = () => {
                    temporaryFileReader.abort();
                    reject(new DOMException("Problem parsing input file."));
                };
                temporaryFileReader.addEventListener("load", function () {
                    var data = {
                        content: temporaryFileReader.result.split(',')[1]
                    };
                    console.log(data);
                    resolve(data);
                }, false);
                temporaryFileReader.readAsDataURL(inputFile.files[0]);
            });
        };
    </script>
</body>

Index.razor

@inject IJSRuntime JSRunTime;
@inject HttpClient Http;
<input type="file" onchange="@UploadFile" id="fileUpload" />
@functions{
    async Task UploadFile()
    {
        var data = await JSRunTime.InvokeAsync<string>("readUploadedFileAsText", "fileUpload");
        var response = await Http.PostAsync("/api/upload", new ByteArrayContent(Convert.FromBase64String(data)));
        var fileTempName = await response.Content.ReadAsStringAsync();
    }
}

UploadController.cs

 [Route("api/upload")]
public class UploadController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> Save()
    {
        return Ok(); // breakpoint here
    }
}

@smartprogrammer93
Copy link

@gojanpolo

No need for steing builder. The code you see is a bit outdated. The response you will get is probably a string so T should be a string. I am not sure if you can use byte array instead

@gojanpaolo
Copy link

@smartprogrammer93 Please see updated https://github.com/aspnet/Blazor/issues/479#issuecomment-498920109. I tried to follow the blog as best I can but it still doesn't seem to work.

@smartprogrammer93
Copy link

@gojanpaolo

I read the code again. And in this case, T should be a string builder. But i am pretty sure if you change the js code to return the content right away instead of a data object with a content property inside it, it could work with steing

@danroth27
Copy link
Member

@gojanpaolo If you're still hitting problems with using HttpClient to send/receive binary data in Blazor please open a new issue in the https://github.com/aspnet/aspnetcore repo with the steps and code needed to reproduce the issue and we'll take a look.

@gojanpaolo
Copy link

@smartprogrammer93 thanks for the suggestions, I tried using StringBuilder instead but doesn't work too. Not sure how to change the js code, it's too foreign for me.

@danroth27 Thank you for responding. I think the issue I'm having is more on how to get file uploading work in client-side blazor. As commented above, it looks like I need to use JSInterop, but I have no experience in javascript. I was hoping there's a way to do it in C#.

@mkArtakMSFT mkArtakMSFT transferred this issue from dotnet/blazor Oct 27, 2019
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Oct 27, 2019
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

No branches or pull requests

10 participants