Coder Social home page Coder Social logo

arivera12 / blazordownloadfile Goto Github PK

View Code? Open in Web Editor NEW
178.0 178.0 25.0 6.1 MB

Blazor download files to the browser from c# without any javascript library reference or dependency.

License: MIT License

C# 30.03% HTML 61.68% CSS 3.67% JavaScript 4.62%
blazor blazordownloadfile csharp

blazordownloadfile's People

Contributors

arivera12 avatar jack-edwards avatar opeca avatar ryoubakura avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

blazordownloadfile's Issues

Downloaded file - when saved - has an Extra null appended to the file

e.g download csv file and save,
Open in winmerge (Or some other tool that supports byte only alignment)
observe a null character at the end of the file.
This fails a "Signature check" because csv have to be ASCII chars only, i.e Alphanumerics with few extras (".,-) etc.
non-printables, back moves, and "Graphics" should fail.

image

Enhancement: Can you show an example of how to get the "Filename" from a `<a>` element

Can you show an example of how to get the "Filename" from a <a> element so that it can be passed into you code for the FileSave ?

e.g. something like

  • Create injected <a> element with a dummy application/unknown encoding that will probably force the SaveAs to popup
  • Get the href / filename / url / whatever from the link after the dummy file has been created.
  • Pass that into you File Saving functionality to replace the file.

Maybe a useful link:
https://stackoverflow.com/questions/61802606/download-file-from-asp-net-core-api-from-blazor-client-application/61803104#61803104

Unable to download an exe file

Hi

I am unable to download an exe file I get "error reload the page" yet I am able to download exe files from websites so I do not think it is a system or browser settings issue.

I am able to download msi files .

Thanks

Laz

V 2.0 `DownloadFile` does not return an error state if the file is not downloaded

I'm passing a "Known" fully encoded URI filename into the DownloadFile API, and then testing for it's existence, but nothing is being returned to say that a fialure has occurred. (Exception etc.

Currently this should fail because it is being used in a Mocked JSInterop environment (BUnit) and therefore no js script function should succeed.

Folder select option

Just want to say, this library was really helpful to me today. Is there a possibility it would support a folder select option? Right now, it defaults to the downloads directory.

I was having an issue with an even smaller size (400kb ish)

I was having an issue with an even smaller size (400kb ish)

I turned my stream into a byte array and it worked.

@arivera12, you might want to impliment this

byte[] myByteArray;
using (var memoryStream = new MemoryStream())
{
    originalStream.CopyTo(memoryStream);
    myByteArray= memoryStream.ToArray();
}

for your

internal static async Task<byte[]> ToByteArrayAsync(this Stream stream)
{
    var streamLength = (int)stream.Length;
    var data = new byte[streamLength];
    stream.Position = 0;
    await stream.ReadAsync(data, 0, streamLength);
    return data;
}

I can submit a PR if you need/like

Originally posted by @thalaeg in #25 (comment)

Support Content-Disposition attachment response downloads for server/remote files.

Problem

When downloading a file from a server directly to JavaScript or Blazor the browser has it's own memory and hardware limitations.

Solution

We should use Content-Disposition attachment response header as it has more cross-browser compatibility.

When using Content-Disposition attachment response header the backing store that the browser uses its the local disk.

This way we will bypass the limitations of the Max File Size of JavaScript and Blazor.

Brainstorming

To make this work with seamless integration we would need to create a JavaScript function which:

  1. Creates dynamic blank window
  2. Creates a dynamic form inside the new window with
    1. action="specified url"
    2. method="specified method"
    3. enctype="specified encode type"
  3. Creates dynamic hidden inputs if an object is provided as argument
  4. Submits the form in that window to the specified url
  5. File download process within the browser should get triggered automatically

Not sure if I am missing something else but this should trigger the file download process within the browser provider and no data should be loaded into memory to JavaScript or Blazor and go straight to the device local disk instead.

Why not an iframe and a window instead?

Iframe will only work on sites that are on the same domain or sites with Access-Control-Allow-Origin response header

If neither of them are considered or present we will hit for sure the same-origin policy error.

Authorization Header

Authorization tokens may be passed down to the new window and form as an input value to be submitted with the rest of the other inputs values.

AFAIK there is no way to pass down authorization token in a header when submitting a form or sending cross domain cookies.

Sample references

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_open3
https://gist.github.com/carlosrivera/768b0c14e083c1ab423f

use memorystreamdata for filecontent

Hello,

iam new to blazor and want to use this package to easily download files. It seems this package makes life easier. Thank you.
In my case i have minimal binary files in sql.
Is it posisble to use this memorystream of blob data for direct download? I noticed in examples all downloads are based on base64 data of binary file. I want to skip a base64 conversion.
Would it be possible to use something like this?

mymemorystream =direct_blobdata_fromsql;
<button @OnClick=@(async () => await BlazorDownloadFileService.DownloadFile("nyan.gif", mymemorystream, BufferSize, "application/octet-stream"))>Dowload Buffered Nyan From Stream

Thank you,
Hans

Unable to download a file larger than 500 MB

Unable to download a file larger than 500 MB.

Used your library, in particular the method: DownloadFile(string filename, Stream stream, CancellationToken cancellationTokenBytesRead, CancellationToken cancellationTokenJavaScriptInterop, string ContentType = "application/octet-stream").

But when you try to download a file larger than 200 MB, an exception occurs, which says that there was not enough memory. Stream was too long

Question on Stackoverflow: https://stackoverflow.com/questions/72356882/generate-a-link-to-the-download-file

Throwing exception when using Content-Security-Policy "script-src 'self' " header

Version: 2.1.6
AspNetCore: 3.1.8

After adding Content-Security-Policy "script-src 'self' " header DownloadFile function started throwing the following exception:

Could not find '_blazorDowloadFileBase64String' in 'window'.
Error: Could not find '_blazorDowloadFileBase64String' in 'window'.
    at http://192.168.0.30:5000/_framework/blazor.server.js:8:30944
    at Array.forEach (<anonymous>)
    at p (http://192.168.0.30:5000/_framework/blazor.server.js:8:30904)
    at http://192.168.0.30:5000/_framework/blazor.server.js:8:31614
    at new Promise (<anonymous>)
    at e.beginInvokeJSFromDotNet (http://192.168.0.30:5000/_framework/blazor.server.js:8:31587)
    at http://192.168.0.30:5000/_framework/blazor.server.js:1:20052
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (http://192.168.0.30:5000/_framework/blazor.server.js:1:20022)
    at e.processIncomingData (http://192.168.0.30:5000/_framework/blazor.server.js:1:18006)

Download Excel file

Hi, can you please show me how to download excel or csv file from list of objects?
thanks a lot.

Trying to Download PDF but cant open it after download

` var buffer = new MemoryStream();
var writer = new BinaryWriter(buffer);

        writer.Write("Student Number: " + studentNumber + "\r\n");
        writer.Write("Module: " + selectedModule + "\r\n");
        writer.Write("ACW: " + selectedACW + "\r\n");
        writer.Write("\r\n");


        writer.Write("Section 1" + "\r\n");
        writer.Write("Section: " + selectedSection1 + "\r\n");
        writer.Write("Criteria: " + selectedCriteria1 + "\r\n");
        writer.Write("Feedback: " + selectedFeedback1.Trim() + " - " + selectedFeedback1grade + "\r\n");
        writer.Write("\r\n");

        if (sectionCounter >= 2)
        {
            writer.Write("Section 2" + "\r\n");
            writer.Write("Section: " + selectedSection2 + "\r\n");
            writer.Write("Criteria: " + selectedCriteria2 + "\r\n");
            writer.Write("Feedback: " + selectedFeedback2.Trim() + " - " + selectedFeedback2grade + "\r\n");
            writer.Write("\r\n");
        }
        if (sectionCounter == 3)
        {
            writer.Write("Section 3" + "\r\n");
            writer.Write("Section: " + selectedSection3 + "\r\n");
            writer.Write("Criteria: " + selectedCriteria3 + "\r\n");
            writer.Write("Feedback: " + selectedFeedback3.Trim() + " - " + selectedFeedback3grade + "\r\n");
            writer.Write("\r\n");
        }
        int grade = selectedFeedback1grade + selectedFeedback2grade + selectedFeedback3grade;
        writer.Write("Overall Grade is: " + grade);

        writer.Close();
        byte[] bytes = buffer.ToArray();
        var task = await BlazorDownloadFileService.DownloadFile($"{studentNumber}.pdf", bytes, 1024 * 64, "application/octet-stream");

    }`          

Trying to download a PDF but everytime I try top open it, I get an error saying its corrupt or not encoded
Thanks!

Stream not working as expected

First of all, thanks for making this library. I still see a JS dependency in version 1.0.10 that is on nuget.

When I use this code:

        using var stream = new MemoryStream();
        wb.Save(stream, SaveOptions.XlsxDefault); //An Excel spreadsheet
        BlazorDownloadFileService.DownloadFile("SaviAnalysis-PROCs.xlsx", stream, "application/octet-stream");

It does not work and seems to treat the stream as empty. However, this code does work:

        using var stream = new MemoryStream();
        wb.Save(stream, SaveOptions.XlsxDefault);
        BlazorDownloadFileService.DownloadFile("SaviAnalysis-PROCs.xlsx", stream.ToArray(), "application/octet-stream");

namespaces not fount

hi i justinstall the package and import in my program.cs the
builder.Services.AddBlazorDownloadFile();
and when i am trying to use this line in a blazor page
[Inject]
public IBlazorDownloadFileService BlazorDownloadFileService { get; set; }

i got this error:

Error CS0246 Type or namespace name 'IBlazorDownloadFileService' not found (is a using directive or assembly reference missing?)

i try too using the @Inject IBlazorDownloadFileService BlazorDownloadFileService but stilll got the same error.

i am using WPA with 5.NET

Add support for file encoding

We are generating a CSV file with a StringBuilder.

Once the StringBuilder is build we want to download the generated content as file with BlazorDownloadFile.

await downloadService.DownloadFileFromText("StarMoney_SepaImport.csv", sb.ToString(), "text/plain");

The file will be downloaded with UTF-8 encoding but we need ISO-8859-1 in our case. So it would be nice if we can pass the encoding to the download methods.

How to speed up download?

Hi

I increased the buffer size and I am now able to download my 110MB exe file but it takes 2 minutes for the download dialog to appear. I am using Blazor server app.

Is there a way of speeding the download up?

Thanks

Originally posted by @ltemimi in #24 (comment)

Struggling with .xlsx file

I'm not sure where the fault lies here is the server side code
return File(fileContents: excelFile, contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
excelFile is a byte array produced using the EPPlus.

Then client side :
byte[] bytes = await httpResponseMessage.Content.ReadAsByteArrayAsync(); await BlazorDownloadFileService.DownloadFile("test555.xlsx", bytes);

The file that is "downloaded" in the browser is corrupt and won't open in Excel. The file that is downloaded is twice as big as the proper/working version of the file that I save server side using EPPlus.

Feature request: Ability to configure IBlazorDownloadFileService lifetime

I need a singleton instance of BlazorDownloadFileService (internal class).

Please allow configuring registering IBlazorDownloadFileService.

Expected api:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddBlazorDownloadFile(Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime);
    }
}


EF.Core allows configuring DbContext lifetime.

public static IServiceCollection Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.AddDbContext<TContext>(
    [NotNull] this IServiceCollection serviceCollection,
    [CanBeNull] Action<DbContextOptionsBuilder> optionsAction = null,
    ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
    ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)

Downloading PDF in Firefox redirects to blob://

Hi!

Since a week we are having issues with downloading files in Firefox.

I have this piece of code:

public async override Task DownloadAsync(bool confirmed = false)
{
    using FbController2 fbController = new FbController2();
    var angebot = await Angebot.GetAngebotAsync(Angebotsnummer, fbController);

    if (angebot is not null)
    {

        PrintAngebotRegelsatz printRegeln = new PrintAngebotRegelsatz
        {
            ShowFooter = true,
            ShowHeader = true
        };


        PrintAngebot angebotPrinter = await PrintAngebot.CreateAsync(angebot, printRegeln, fbController);
        // Generates th PDF file and returns the full file path
        string filenameAngebotPdf = angebotPrinter.Print(GlobalConfig.Configuration.OutputPfad);
    
    
        await downloadService.DownloadFile($"AN-{Angebotsnummer}.pdf", await File.ReadAllBytesAsync(filenameAngebotPdf), "application/pdf");
        await downloadService.ClearBuffers();
    }

    _isDownloading = false;
}

As you can see, I want to download AN-XXXXX.pdf which becomes generated one line before. Downloading the PDF will result in Firefox redircet to a blob:// url which displays the PDF.
blob:https://localhost:5001/275606a8-d314-4674-9f2d-44fa282e4da9

I'm running Windows 10 Professional 21H1 64 Bit with Firefox 98.0.2 with German locale. It works in Chrome and Edge.

[Enhancement] Dispose object url after no longer needed

Memory management

Each time you call URL.createObjectURL(), a new object URL is created, even if you've already created one for the same object. Each of these must be released by calling URL.revokeObjectURL() when you no longer need them.

Browsers will release object URLs automatically when the document is unloaded; however, for optimal performance and memory usage, if there are safe times when you can explicitly unload them, you should do so.

Reference links:
https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL

Upgrade and test NET6

Hello @arivera12, I'd recommend skipping .NET 5 and going straight to .NET 6 in this case as .NET 6 has significant improvements to the byte array interop mechanisms.

Blazor no longer Base64 encodes/decodes byte[], and also natively supports streaming via JSStreamReference/DotNetStreamReference. This'll provide SIGNIFICANT improvements to stability and performance over .NET 5 in this area.

Links:

Originally posted by @TanayParikh in #28 (comment)

Can "the buffer management" solution, also have a way of

Can "the buffer management" solution, also have a way of

  • Starting a save
  • Adding many buffers (as they are downloaded to save having to create a single monster ManyGB memory stream and blowing the blazor VM)
  • Committing the save (Or auto dispose if exception thrown etc.)

As per a rework of the gist above ?

Originally posted by @Smurf-IV in #5 (comment)

Unable to download large file (Via byte[] or stream)

  • Using V 2.1.6
  • .NetCore 3.1
  • Hosted in Chrome 87

I have a memory stream that is 280803689 bytes
I have direct access to the buffer it contains via var bytes = ms.GetBuffer();

I then call
DowloadFileResult fileResult = await DownloadFileService.DownloadFile(FileDetails.OriginalFileName, bytes, cts.Token, 1024*64, "application/octet-stream", OnProgress);
Then 6 minutes later I get this:

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
      Unhandled exception rendering component: Out of memory
System.OutOfMemoryException: Out of memory
  at (wrapper managed-to-native) System.String.FastAllocateString(int)
  at System.String.CreateStringFromEncoding (System.Byte* bytes, System.Int32 byteLength, System.Text.Encoding encoding) <0x2fd3328 + 0x00030> in <filename unknown>:0 
  at System.Text.Encoding.GetString (System.Byte* bytes, System.Int32 byteCount) <0x2fd3170 + 0x0004e> in <filename unknown>:0 
  at System.Text.Json.JsonReaderHelper.TranscodeHelper (System.ReadOnlySpan`1[T] utf8Unescaped) <0x32b9e68 + 0x0004a> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.WriteCoreString (System.Object value, System.Type type, System.Text.Json.JsonSerializerOptions options) <0x356b5a0 + 0x00074> in <filename unknown>:0 
  at System.Text.Json.JsonSerializer.Serialize[TValue] (TValue value, System.Text.Json.JsonSerializerOptions options) <0x356b210 + 0x0000c> in <filename unknown>:0 
  at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue] (System.String identifier, System.Threading.CancellationToken cancellationToken, System.Object[] args) <0x3563820 + 0x001f4> in <filename unknown>:0 
  at Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync (Microsoft.JSInterop.IJSRuntime jsRuntime, System.String identifier, System.Threading.CancellationToken cancellationToken, System.Object[] args) <0xc9b80a0 + 0x0004c> in <filename unknown>:0 
  at BlazorDownloadFile.BlazorDownloadFileService.DownloadFile (System.String fileName, System.Byte[] bytes, System.Threading.CancellationToken cancellationToken, System.Int32 bufferSize, System.String contentType, System.IProgress`1[T] progress) <0x4f21960 + 0x00246> in <filename unknown>:0 
  at System.Threading.Tasks.ValueTask`1[TResult].get_Result () <0x9ce4320 + 0x00034> in <filename unknown>:0 
  at ```

I call Garbage collect before calling the Download function to make sure there is plenty of available memory:

L: GC_MAJOR_SWEEP: major size: 2512K in use: 1523K
L: GC_MAJOR: (user request) time 63.28ms, stw 63.30ms los size: 450736K in use: 449168K

I have tried to use the `Memory stream` **directly** but it just drop 5MB of the file after about 3 minutes.
Also the `Progress Callback` is **only** called once !

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.