Skip to content

Commit

Permalink
Implemented buffered downloads. Byte Array and Streams still needs wo…
Browse files Browse the repository at this point in the history
…rk. Base64 buffered works properly in the meantime. Added js vars clean up afte use. Added samples. Improved and fix documentation.
  • Loading branch information
Anthony Rivera committed Jul 24, 2020
1 parent 43658f2 commit f64ef3d
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 206 deletions.
2 changes: 1 addition & 1 deletion BlazorDownloadFile.Demo/Pages/DownloadFileFromText.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@page "/DownloadFileFromText"
<h1>Download File From Text</h1>

<button @onclick=@(async () => await BlazorDownloadFileService.DownloadFileFromText("test.json", json))>Dowload json from text</button>
<button @onclick=@(async () => await BlazorDownloadFileService.DownloadFileFromText("test.json", json, "application/octet-stream"))>Dowload json from text</button>
<br />
<br />
<pre>@json</pre>
Expand Down
23 changes: 18 additions & 5 deletions BlazorDownloadFile.Demo/Pages/Index.razor

Large diffs are not rendered by default.

23 changes: 1 addition & 22 deletions BlazorDownloadFile/Extensions/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,11 @@ internal static class StreamExtensions
internal static byte[] ToByteArray(this Stream stream)
{
var bytes = (stream as MemoryStream).ToArray();

This comment has been minimized.

Copy link
@Smurf-IV

Smurf-IV Jul 24, 2020

Need to check if it is a memory stream first, and default to another method if not.

This comment has been minimized.

Copy link
@arivera12

arivera12 Jul 24, 2020

Owner

Makes sense

stream.Flush();

This comment has been minimized.

Copy link
@Smurf-IV

Smurf-IV Jul 24, 2020

Should the flush be done before the conversion to Array ?

This comment has been minimized.

Copy link
@arivera12

arivera12 Jul 24, 2020

Owner

Flush clears the buffer. Not sure if clear the current buffer or the entire stream buffer, need to take a deep look.

stream.Close();

This comment has been minimized.

Copy link
@Smurf-IV

Smurf-IV Jul 24, 2020

Need to state that the stream will closed and disposed in the intellisense, as I do not use a memory stream, and like to re-use my NonContig (Not LOH allocation) stream.

This comment has been minimized.

Copy link
@arivera12

arivera12 Jul 24, 2020

Owner

Ok, i will leave the stream management and GC open for developers, make sense if you wanna do something else with the stream.

stream.Dispose();
GC.Collect(1, GCCollectionMode.Forced);

This comment has been minimized.

Copy link
@Smurf-IV

Smurf-IV Jul 24, 2020

Add comment as to why this is needed as it will cause the Blazor single thread to pause unexpectedly.

return bytes;
}
///// <summary>
///// Converts a stream into a byte array
///// </summary>
///// <param name="stream">The stream</param>
///// <param name="bufferSize">The buffer size</param>
///// <returns></returns>
//internal static byte[] ToByteArray(this Stream stream, int bufferSize)
//{
// var buffer = new byte[bufferSize];
// for (int index = 0; index < ((int)(stream as MemoryStream).Length / bufferSize); index++)
// {
// yield return (byte)(stream as MemoryStream).get(buffer, 0, (int)stream.Length);
// }
// foreach (var bytes in (stream as MemoryStream).ReadByte(buffer, 0, (int)stream.Length))
// {

// }
// stream.Close();
// stream.Dispose();
// GC.Collect(1, GCCollectionMode.Forced);
// return bytes;
//}
}
}
178 changes: 126 additions & 52 deletions BlazorDownloadFile/Script/DownloadFileScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,43 @@ internal class DownloadFileScript
/// <param name="fileName"></param>
/// <param name="bytesBase64"></param>
/// <returns></returns>
public static string DownloadFileJavascriptScript(string fileName, string bytesBase64, string contentType)
public static string DownloadFileJavascriptScriptBase64String(string fileName, string bytesBase64, string contentType)
{
return $@"
if (navigator.msSaveBlob)
{{
//Download document in Edge browser
var data = window.atob(""{bytesBase64}"");
var bytes = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {{
bytes[i] = data.charCodeAt(i);
var _blazorDownloadFileData = atob(""{bytesBase64}"");
var _blazorDownloadFileBytes = new Uint8Array(_blazorDownloadFileData.length);
for (var i = 0; i < _blazorDownloadFileData.length; i++) {{
_blazorDownloadFileBytes[i] = _blazorDownloadFileData.charCodeAt(i);
}}
var blob = new Blob([bytes.buffer], {{ type: ""{contentType}"" }});
navigator.msSaveBlob(blob, ""{fileName}"");
_blazorDownloadFileData = null;
var _blazorDownloadFileBlob = new Blob([_blazorDownloadFileBytes.buffer], {{ type: ""{contentType}"" }});
_blazorDownloadFileBytes = null;
navigator.msSaveBlob(_blazorDownloadFileBlob, ""{fileName}"");
_blazorDownloadFileBlob = null;
}}
else
{{
var link = document.createElement('a');
link.download = ""{fileName}"";
link.style.display = ""none"";
link.href = ""data:{contentType};base64,"" + ""{bytesBase64}"";
document.body.appendChild(link); // Needed for Firefox
link.click();
document.body.removeChild(link);
//Download document in other browser
var _blazorDownloadFileData = atob(""{bytesBase64}"");
var _blazorDownloadFileBytes = new Uint8Array(_blazorDownloadFileData.length);
for (var i = 0; i < _blazorDownloadFileData.length; i++) {{
_blazorDownloadFileBytes[i] = _blazorDownloadFileData.charCodeAt(i);
}}
_blazorDownloadFileData = null;
var _blazorDownloadFileBlob = new Blob([_blazorDownloadFileBytes.buffer], {{ type: ""{contentType}"" }});
_blazorDownloadFileBytes = null;
var _blazorDownloadFileLink = document.createElement(""a"");
_blazorDownloadFileLink.download = ""{fileName}"";
_blazorDownloadFileLink.style.display = ""none"";
_blazorDownloadFileLink.href = URL.createObjectURL(_blazorDownloadFileBlob);
document.body.appendChild(_blazorDownloadFileLink); // Needed for Firefox
_blazorDownloadFileLink.click();
_blazorDownloadFileBlob = null;
document.body.removeChild(_blazorDownloadFileLink);
_blazorDownloadFileLink = null;
}}";
}
/// <summary>
Expand All @@ -39,72 +53,132 @@ public static string DownloadFileJavascriptScript(string fileName, string bytesB
/// <param name="fileName"></param>
/// <param name="bytesBase64"></param>
/// <returns></returns>
public static string DownloadFileJavascriptScript(string fileName, string contentType)
public static string DownloadFileJavascriptScriptBase64StringPartitioned(string fileName, string contentType)
{
return $@"
var BlazorDownloadFileBufferParts = new Array();
for (var base64Part in BlazorDownloadFileBuffer) {{
var bytes = new Uint8Array(base64Part.length);
for (var i = 0; i < base64Part.length; i++) {{
bytes[i] = base64Part.charCodeAt(i);
}}
BlazorDownloadFileBufferParts.push(bytes);
}}
var blob = new Blob(BlazorDownloadFileBufferParts, {{ type: ""{contentType}"" }});
if (navigator.msSaveBlob)
{{
//Download document in Edge browser
navigator.msSaveBlob(blob, ""{fileName}"");
var _blazorDownloadFileData = atob(_blazorDownloadFileBase64Buffers.join(""""));
_blazorDownloadFileBase64Buffers = null;
var _blazorDownloadFileBytes = new Uint8Array(_blazorDownloadFileData.length);
for (var i = 0; i < _blazorDownloadFileData.length; i++) {{
_blazorDownloadFileBytes[i] = _blazorDownloadFileData.charCodeAt(i);
}}
_blazorDownloadFileData = null;
var _blazorDownloadFileBlob = new Blob([_blazorDownloadFileBytes.buffer], {{ type: ""{contentType}"" }});
_blazorDownloadFileBytes = null;
navigator.msSaveBlob(_blazorDownloadFileBlob, ""{fileName}"");
_blazorDownloadFileBlob = null;
}}
else
{{
var link = document.createElement('a');
link.download = ""{fileName}"";
link.style.display = ""none"";
link.href = URL.createObjectURL(blob);
document.body.appendChild(link); // Needed for Firefox
link.click();
document.body.removeChild(link);
//Download document in other browser
var _blazorDownloadFileBase64BufferParts = new Array();
for(var _blazorDownloadFileBase64Buffer in _blazorDownloadFileBase64Buffers) {{
var _blazorDownloadFileData = atob(_blazorDownloadFileBase64Buffer);
var _blazorDownloadFileBytes = new Uint8Array(_blazorDownloadFileData.length);
for (var i = 0; i < _blazorDownloadFileData.length; i++) {{
_blazorDownloadFileBytes[i] = _blazorDownloadFileData.charCodeAt(i);
}}
_blazorDownloadFileBase64BufferParts.push(_blazorDownloadFileBytes);
_blazorDownloadFileBytes = null;
_blazorDownloadFileData = null;
}}
_blazorDownloadFileBase64Buffers = null;
var _blazorDownloadFileBlob = new Blob(_blazorDownloadFileBase64BufferParts, {{ type: ""{contentType}"" }});
_blazorDownloadFileBase64BufferParts = null;
var _blazorDownloadFileLink = document.createElement(""a"");
_blazorDownloadFileLink.download = ""{fileName}"";
_blazorDownloadFileLink.style.display = ""none"";
_blazorDownloadFileLink.href = URL.createObjectURL(_blazorDownloadFileBlob);
document.body.appendChild(_blazorDownloadFileLink); // Needed for Firefox
_blazorDownloadFileLink.click();
_blazorDownloadFileBlob = null;
document.body.removeChild(_blazorDownloadFileLink);
_blazorDownloadFileLink = null;
}}";
}
/// <summary>
/// Adds file to javascript native buffer
/// The download script of the file
/// </summary>
/// <param name="fileName"></param>
/// <param name="bytesBase64"></param>
/// <returns></returns>
public static string AddFileBuffer(char bytesBase64)
// public static string DownloadFileJavascriptScriptByteArrayPartitioned(string fileName, string contentType)
// {
// return $@"
//if (navigator.msSaveBlob)
//{{
// //Download document in Edge browser
// var bytes = new Uint8Array(_blazorDownloadFileByteArrayBuffer.length);
// for (var i = 0; i < _blazorDownloadFileByteArrayBuffer.length; i++) {{
// bytes[i] = _blazorDownloadFileByteArrayBuffer[i];
// }}
// var blob = new Blob([bytes.buffer], {{ type: ""{contentType}"" }});
// _blazorDownloadFileByteArrayBuffer = null;
// parts = null;
// navigator.msSaveBlob(blob, ""{fileName}"");
//}}
//else
//{{
// //Download document in other browser
// var parts = new Array();
// for (var base64Part in _blazorDownloadFileByteArrayBuffer) {{
// var bytes = new Uint8Array(_blazorDownloadFileByteArrayBuffer.length);
// for (var i = 0; i < base64Part.length; i++) {{
// bytes[i] = base64Part.charCodeAt(i);
// }}
// parts.push(bytes);
// }}
// var blob = new Blob(parts, {{ type: ""{contentType}"" }});
// //_blazorDownloadFileByteArrayBuffer = null;
// //parts = null;
// var link = document.createElement(""a"");
// link.download = ""{fileName}"";
// link.style.display = ""none"";
// link.href = URL.createObjectURL(blob);
// document.body.appendChild(link); // Needed for Firefox
// link.click();
// document.body.removeChild(link);
//}}
//";
// }
/// <summary>
/// Initializes BlazorDownloadFileBuffer on JavaScript
/// </summary>
/// <returns></returns>
public static string InitializeBlazorDownloadFileBuffer()
{
return $@"
if(typeof BlazorDownloadFileBuffer === 'undefined')
if(typeof _blazorDownloadFileBase64Buffers === 'undefined')
{{
var BlazorDownloadFileBuffer = new Array();
var _blazorDownloadFileBase64Buffers = new Array();
}}
if(BlazorDownloadFileBuffer === null)
if(_blazorDownloadFileBase64Buffers === null)
{{
BlazorDownloadFileBuffer = new Array();
}}
BlazorDownloadFileBuffer.push({bytesBase64});";
_blazorDownloadFileBase64Buffers = new Array();
}}";
}
/// <summary>
/// Adds file to javascript native buffer
/// </summary>
/// <param name="fileName"></param>
/// <param name="bytesBase64"></param>
/// <returns></returns>
public static string AddFileBuffer(string bytesBase64)
public static string AddFileBufferBase64StringPartition(string bytesBase64)
{
return $@"
if(typeof BlazorDownloadFileBuffer === 'undefined')
{{
var BlazorDownloadFileBuffer = new Array();
}}
if(BlazorDownloadFileBuffer === null)
{{
BlazorDownloadFileBuffer = new Array();
}}
BlazorDownloadFileBuffer.push({bytesBase64});";
_blazorDownloadFileBase64Buffers.push(""{bytesBase64}"");";
}
/// <summary>
/// Adds file to javascript native buffer
/// </summary>
/// <param name="bytesBase64"></param>
/// <returns></returns>
public static string AddFileBufferDoubledBase64StringPartition(string bytesBase64)
{
return $@"
_blazorDownloadFileBase64Buffers.push(btoa(""{bytesBase64}""));";
}

}
}

0 comments on commit f64ef3d

Please sign in to comment.