axios({ url: 'http://localhost:5000/static/example.pdf', method: 'GET', responseType: 'blob', // important }).then((response) => { const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'file.pdf'); document.body.appendChild(link); link.click(); });
https://github.com/kennethjiang/js-file-download/blob/master/file-download.js
module.exports = function(data, filename, mime, bom) { var blobData = (typeof bom !== 'undefined') ? [bom, data] : [data] var blob = new Blob(blobData, {type: mime || 'application/octet-stream'}); if (typeof window.navigator.msSaveBlob !== 'undefined') { // IE workaround for "HTML7007: One or more blob URLs were // revoked by closing the blob for which they were created. // These URLs will no longer resolve as the data backing // the URL has been freed." window.navigator.msSaveBlob(blob, filename); } else { var blobURL = (window.URL && window.URL.createObjectURL) ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob); var tempLink = document.createElement('a'); tempLink.style.display = 'none'; tempLink.href = blobURL; tempLink.setAttribute('download', filename); // Safari thinks _blank anchor are pop ups. We only want to set _blank // target if the browser does not support the HTML5 download attribute. // This allows you to download files in desktop safari if pop up blocking // is enabled. if (typeof tempLink.download === 'undefined') { tempLink.setAttribute('target', '_blank'); } document.body.appendChild(tempLink); tempLink.click(); // Fixes "webkit blob resource error 1" setTimeout(function() { document.body.removeChild(tempLink); window.URL.revokeObjectURL(blobURL); }, 200) } }
You must be familiar with axios calls for API consumption, but what about getting the files in response and render those files to the user for download. We got your covered, the below snippet is tested and works well.
axios({ url: 'http://api.dev/file-download', method: 'GET', responseType: 'blob', // important }).then((response) => { const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'file.pdf'); //or any other extension document.body.appendChild(link); link.click(); });
Credits to this Javilobo for his useful Solution.
You can check https://github.com/kennethjiang/js-file-download/blob/master/file-download.js to see how to handle IE download stuff.
Sometimes server will provide an interface with application/octet-stream
, usually it's related with file operator, so how we handle this using js?
Actually it's very easy, make it as a download content will be okay.
e.g.
cache-control: no-cache, no-store, max-age=0, must-revalidate connection: close content-disposition: attachment; filename=111.txt content-type: application/octet-stream Date: Mon, 28 Jan 2019 08:31:00 GMT expires: 0 pragma: no-cache referrer-policy: no-referrer transfer-encoding: chunked x-content-type-options: nosniff x-frame-options: DENY X-Powered-By: Express x-xss-protection: 1 ; mode=block
We can handle this response by following codes:
function handleResponse = response => { response.blob().then(blob => { const link = document.createElement('a'); const url = URL.createObjectURL(blob); console.log(url); link.href = url; link.download = '111.txt'; link.click(); }) }
If an EC2 log records events in XML format, then every XML event will record EC2-related information as a base64 string. In order to run analytics on this data using Apache Spark, you need to use the spark_xml
library and BASE64DECODER
API to transform this data for analysis. In this article:
Problem
You need to analyze base64-encoded strings from an XML-formatted log file using Spark. For example, the following file input.xml
shows this type of format: XML Copy
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log [<!ENTITY % log SYSTEM "aws_instance">%log;]> <log systemID="MF2018" timeZone="UTC" timeStamp="Mon Mar 25 16:00:01 2018"> <message source="ec2.log" time="Mon Mar 25 16:00:01 2018" type="sysMSG"><text/> <detail> <blob>aW5zdGFuY2VJZCxzdGFydFRpbWUsZGVsZXRlVGltZSxob3Vycw0KaS0wMjdmYTdjY2RhMjEwYjRmNCwyLzE3LzE3VDIwOjIxLDIvMTcvMTdUMjE6MTEsNQ0KaS0wN2NkNzEwMGUzZjU0YmY2YSwyLzE3LzE3VDIwOjE5LDIvMTcvMTdUMjE6MTEsNA0KaS0wYTJjNGFkYmYwZGMyNTUxYywyLzE3LzE3VDIwOjE5LDIvMTcvMTdUMjE6MTEsMg0KaS0wYjQwYjE2MjM2Mzg4OTczZiwyLzE3LzE3VDIwOjE4LDIvMTcvMTdUMjE6MTEsNg0KaS0wY2ZkODgwNzIyZTE1ZjE5ZSwyLzE3LzE3VDIwOjE4LDIvMTcvMTdUMjE6MTEsMg0KaS0wY2YwYzczZWZlZWExNGY3NCwyLzE3LzE3VDE2OjIxLDIvMTcvMTdUMTc6MTEsMQ0KaS0wNTA1ZTk1YmZlYmVjZDZlNiwyLzE3LzE3VDE2OjIxLDIvMTcvMTdUMTc6MTEsOA== </blob> </detail> </message> </log>
Solution
To parse the XML file:
- Load the XML data.
- Use the spark_xml
library and create a raw DataFrame
. - Apply a base64 decoder on the blob column using the BASE64Decoder
API. - Save the decoded data in a text file (optional).
- Load the text file using the Spark DataFrame
and parse it. - Create the DataFrame
as a Spark SQL table.
The following Scala code processes the file:
Scala Copy
val xmlfile = "/mnt/vgiri/input.xml" val readxml = spark.read.format("com.databricks.spark.xml").option("rowTag","message").load(xmlfile) val decoded = readxml.selectExpr("_source as source","_time as time","_type as type","detail.blob") decoded.show() //Displays the raw blob data //Apply base64 decoder on every piece of blob data as shown below val decodethisxmlblob = decoded.rdd .map(str => str(3).toString) .map(str1 => new String(new sun.misc.BASE64Decoder() .decodeBuffer(str1))) //Store it in a text file temporarily decodethisxmlblob.saveAsTextFile("/mnt/vgiri/ec2blobtotxt") //Parse the text file as required using Spark DataFrame. val readAsDF = spark.sparkContext.textFile("/mnt/vgiri/ec2blobtotxt") val header = readAsDF.first() val finalTextFile = readAsDF.filter(row => row != header) val finalDF = finalTextFile.toDF() .selectExpr( ("split(value, ',')[0] as instanceId"), ("split(value, ',')[1] as startTime"), ("split(value, ',')[2] as deleteTime"), ("split(value, ',')[3] as hours") ) finalDF.show()
40
I had the same problem as you. It turns out you need to convert the Excel data file to an ArrayBuffer.
var blob = new Blob([s2ab(atob(data))], { type: '' }); href = URL.createObjectURL(blob);
The s2ab (string to array buffer) method (which I got from https://github.com/SheetJS/js-xlsx/blob/master/README.md) is:
function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; return buf; }
share improve this answer follow answered Mar 1 '16 at 2:27 Ron T 51544 silver badges88 bronze badges
- 6 this doesn't seem to work with raw data (I.e. the excel file returned by a server as-is). In fact "s" returns undefined. any clue? – dragonmnl Jul 6 '17 at 10:33
- @Ron T what's atob? – tjvg1991 Mar 2 '19 at 13:14
- @tjvg1991: It's the function, window.atob(). What is stands for and what it does is explained here: stackoverflow.com/questions/33854103/… – Ron T Mar 4 '19 at 1:19
The answer above is correct. Please be sure that you have a string data in base64 in the data variable without any prefix or stuff like that just raw data.
Here's what I did on the server side (asp.net mvc core):
string path = Path.Combine(folder, fileName); Byte[] bytes = System.IO.File.ReadAllBytes(path); string base64 = Convert.ToBase64String(bytes);
On the client side, I did the following code:
const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.setRequestHeader("Content-Type", "text/plain"); xhr.onload = () => { var bin = atob(xhr.response); var ab = s2ab(bin); // from example above var blob = new Blob([ab], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = 'demo.xlsx'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; xhr.send();
And it works perfectly for me.
5
This works as of: v0.14.0 of https://github.com/SheetJS/js-xlsx
/* generate array buffer */ var wbout = XLSX.write(wb, {type:"array", bookType:'xlsx'}); /* create data URL */ var url = URL.createObjectURL(new Blob([wbout], {type: 'application/octet-stream'})); /* trigger download with chrome API */ chrome.downloads.download({ url: url, filename: "testsheet.xlsx", saveAs: true });
try FileSaver.js
library. it might help.
https://github.com/eligrey/FileSaver.js/
eligrey/FileSaver.js/* * FileSaver.js * A saveAs() FileSaver implementation. * * By Eli Grey, http://eligrey.com * * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT) * source : http://purl.eligrey.com/github/FileSaver.js */ // The one and only way of getting global scope in all environments // https://stackoverflow.com/q/3277182/1008999 var _global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : this function bom (blob, opts) { if (typeof opts === 'undefined') opts = { autoBom: false } else if (typeof opts !== 'object') { console.warn('Deprecated: Expected third argument to be a object') opts = { autoBom: !opts } } // prepend BOM for UTF-8 XML and text/* types (including HTML) // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type }) } return blob } function download (url, name, opts) { var xhr = new XMLHttpRequest() xhr.open('GET', url) xhr.responseType = 'blob' xhr.onload = function () { saveAs(xhr.response, name, opts) } xhr.onerror = function () { console.error('could not download file') } xhr.send() } function corsEnabled (url) { var xhr = new XMLHttpRequest() // use sync to avoid popup blocker xhr.open('HEAD', url, false) try { xhr.send() } catch (e) {} return xhr.status >= 200 && xhr.status <= 299 } // `a.click()` doesn't work for all browsers (#465) function click (node) { try { node.dispatchEvent(new MouseEvent('click')) } catch (e) { var evt = document.createEvent('MouseEvents') evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null) node.dispatchEvent(evt) } } // Detect WebView inside a native macOS app by ruling out all browsers // We just need to check for 'Safari' because all other browsers (besides Firefox) include that too // https://www.whatismybrowser.com/guides/the-latest-user-agent/macos var isMacOSWebView = _global.navigator && /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent) var saveAs = _global.saveAs || ( // probably in some web worker (typeof window !== 'object' || window !== _global) ? function saveAs () { /* noop */ } // Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView : ('download' in HTMLAnchorElement.prototype && !isMacOSWebView) ? function saveAs (blob, name, opts) { var URL = _global.URL || _global.webkitURL var a = document.createElement('a') name = name || blob.name || 'download' a.download = name a.rel = 'noopener' // tabnabbing // TODO: detect chrome extensions & packaged apps // a.target = '_blank' if (typeof blob === 'string') { // Support regular links a.href = blob if (a.origin !== location.origin) { corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank') } else { click(a) } } else { // Support blobs a.href = URL.createObjectURL(blob) setTimeout(function () { URL.revokeObjectURL(a.href) }, 4E4) // 40s setTimeout(function () { click(a) }, 0) } } // Use msSaveOrOpenBlob as a second approach : 'msSaveOrOpenBlob' in navigator ? function saveAs (blob, name, opts) { name = name || blob.name || 'download' if (typeof blob === 'string') { if (corsEnabled(blob)) { download(blob, name, opts) } else { var a = document.createElement('a') a.href = blob a.target = '_blank' setTimeout(function () { click(a) }) } } else { navigator.msSaveOrOpenBlob(bom(blob, opts), name) } } // Fallback to using FileReader and a popup : function saveAs (blob, name, opts, popup) { // Open a popup immediately do go around popup blocker // Mostly only available on user interaction and the fileReader is async so... popup = popup || open('', '_blank') if (popup) { popup.document.title = popup.document.body.innerText = 'downloading...' } if (typeof blob === 'string') return download(blob, name, opts) var force = blob.type === 'application/octet-stream' var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent) if ((isChromeIOS || (force && isSafari) || isMacOSWebView) && typeof FileReader !== 'undefined') { // Safari doesn't allow downloading of blob URLs var reader = new FileReader() reader.onloadend = function () { var url = reader.result url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;') if (popup) popup.location.href = url else location = url popup = null // reverse-tabnabbing #460 } reader.readAsDataURL(blob) } else { var URL = _global.URL || _global.webkitURL var url = URL.createObjectURL(blob) if (popup) popup.location = url else location.href = url popup = null // reverse-tabnabbing #460 setTimeout(function () { URL.revokeObjectURL(url) }, 4E4) // 40s } } ) _global.saveAs = saveAs.saveAs = saveAs if (typeof module !== 'undefined') { module.exports = saveAs; }