https://codexpert.ro/blog/2013/11/04/fill-a-list-with-large-amount-of-data-part-2/
<a class="download-link" title="
Version 1 " href="https://codexpert.ro/blog/download/1807/?tmstv=1676620767" rel="nofollow">
Virtual_List_Demo.zip (2192 downloads)
</a>
jQuery(function(e) { new DLM_XHR_Download }); class DLM_XHR_Download { constructor() { (dlmXHRinstance = this).init() } init() { dlmXHRinstance.attachButtonEvent() } attachButtonEvent() { jQuery("html, body").on("click", ".dlm-no-access-modal-overlay, .dlm-no-access-modal-close", function(e) { jQuery("#dlm-no-access-modal").remove() }), jQuery("html, body").on("click", "a", function(e) { const d = jQuery(this).attr("href"); if (jQuery(this).hasClass("dlm-no-xhr-download")) return !0; void 0 !== d && 0 <= d.indexOf(dlmXHRGlobalLinks) && dlmXHRinstance.handleDownloadClick(this, e) }) } handleDownloadClick(e, d) { d.stopPropagation(); var o = e.getAttribute("href"); let t = { button: e, href: o, buttonObj: jQuery(e) }; -1 === t.href.indexOf("blob:http") && "#" !== t.href && (d.preventDefault(), dlmXHRinstance.retrieveBlob(t)) } retrieveBlob(e) { let {button: n, href: l, buttonObj: a} = e, s; const i = new XMLHttpRequest , m = dlmXHR.prevent_duplicates , c = a.attr("target"); let u = a.attr("class"); u = void 0 !== u && "" !== u ? u.replace("dlm-download-started", "").replace("dlm-download-completed", "") : "", a.addClass("dlm-download-started"), n.setAttribute("href", "#"), n.removeAttribute("download"), n.setAttribute("disabled", "disabled"); e = '<img src="' + dlmXHRgif + '" class="dlm-xhr-loading-gif" style="display:inline-block; vertical-align: middle; margin-left:15px;">', n.innerHTML += e, e = 0 < l.indexOf("?") ? l + "&nonce=" + dlmXHR.nonce : l + "?nonce=" + dlmXHR.nonce; jQuery(document).trigger("dlm_download_triggered", [this, n, a, s]), i.responseType = "blob", i.onreadystatechange = function() { var {status: e, readyState: d, statusText: o} = i; let t = i.getAllResponseHeaders().split("\r\n").reduce((e,d)=>{ var [d,o] = d.split(": "); return e[d] = o, e } , {}) , r = "download"; if (void 0 !== t["dlm-file-name"] ? (r = t["dlm-file-name"].replace(/\"/g, "").replace(";", ""), r = decodeURI(r)) : void 0 !== t["content-disposition"] && (r = (r = t["content-disposition"].split("filename=")[1]).replace(/\"/g, "").replace(";", ""), r = decodeURI(r)), 2 === i.readyState) { if (void 0 !== t["dlm-no-waypoints"]) return i.abort(), void 0 !== t["dlm-redirect"] ? void (window.location.href = t["dlm-redirect"]) : void (window.location.href = l); if (void 0 !== t["dlm-external-download"]) return i.abort(), void dlmXHRinstance.dlmExternalDownload(t, n, a, r, l); if (0 === Object.keys(t).filter(e=>-1 !== e.indexOf("dlm-")).length) return i.abort(), void (window.location.href = l); if (void 0 !== t["dlm-no-access"] && "true" === t["dlm-no-access"] && void 0 !== t["dlm-no-access-modal"] && 0 != t["dlm-no-access-modal"]) return dlmXHRinstance.dlmNoAccessModal(t), n.removeAttribute("download"), n.setAttribute("href", l), a.removeClass().addClass(u).find("span.dlm-xhr-progress").remove(), a.find(".dlm-xhr-loading-gif").remove(), void i.abort(); if (void 0 !== t["dlm-error"] && "" !== t["dlm-error"] && null !== t["dlm-error"]) return dlmXHRinstance.dlmLogDownload(t, "failed", !1), n.removeAttribute("download"), n.setAttribute("href", l), a.removeClass().addClass(u).find("span.dlm-xhr-progress").remove(), a.find(".dlm-xhr-loading-gif").remove(), i.abort(), void (void 0 !== t["dlm-no-access-modal"] && 0 != t["dlm-no-access-modal"] ? dlmXHRinstance.dlmNoAccessModal(t["dlm-download-id"], t["dlm-version-id"], t["dlm-no-access-modal-text"]) : a.append('<span class="dlm-xhr-error">' + t["dlm-error"] + "</span>")); if (void 0 !== t["dlm-redirect"] && "" !== t["dlm-redirect"] && null !== t["dlm-redirect"]) return dlmXHRinstance.dlmLogDownload(t, "redirected", !1, t["dlm-redirect"], t["dlm-no-access"], c), n.removeAttribute("download"), n.setAttribute("href", l), a.removeClass().addClass(u).find("span.dlm-xhr-progress").remove(), a.find(".dlm-xhr-loading-gif").remove(), void i.abort() } if (404 == e && 2 == d) { let e = document.createElement("p"); e.innerHTML = o, n.parentNode.appendChild(e) } if (401 == e && 2 == d) window.location.href = o; else { if (403 == e && 2 == d) { let e = document.createElement("p"); e.innerHTML = o, n.parentNode.appendChild(e) } 200 == e && 4 == d && (o = i.response, s = URL.createObjectURL(o), n.removeEventListener("click", dlmXHRinstance.handleDownloadClick), n.setAttribute("download", "" + r), n.setAttribute("href", s), n.click(), a.removeClass().addClass(u + " dlm-download-complete"), dlmXHRinstance.attachButtonEvent(), jQuery(document).trigger("dlm_download_complete", [this, n, a, s]), dlmXHRinstance.dlmLogDownload(t, "completed", m), window.URL.revokeObjectURL(s), n.removeAttribute("download"), n.setAttribute("href", l), a.find(".dlm-xhr-loading-gif").remove(), setTimeout(function() { a.removeClass().addClass(u).find("span.dlm-xhr-progress").remove() }, 4e3)) } } , i.addEventListener("progress", function(e) { let d = e.loaded / e.total * 100; d = d.toFixed(); var o; a.find("span.dlm-xhr-progress").remove(), o = "dlm-download-started download-" + 10 * Math.ceil(d / 10), 1 / 0 != d && a.append('<span class="dlm-xhr-progress"> ' + d + "%</span>"), a.removeClass().addClass(u + " " + o), jQuery(document).trigger("dlm_download_progress", [this, n, a, s, e, d]) }), i.onerror = function() { n.removeAttribute("download"), n.setAttribute("href", l), a.removeClass().addClass(u + " dlm-no-xhr-download").find("span.dlm-xhr-progress").remove(), a.append('<span class="dlm-xhr-error">' + dlmXHRtranslations.error + "</span>"), console.log("** An error occurred during the transaction") } , i.open("GET", e, !0), i.setRequestHeader("dlm-xhr-request", "dlm_XMLHttpRequest"), i.send() } dlmLogDownload(e, d, o, t=null, r=null, n="_self") { null !== r ? window.location.href = t : (r = window.location.href, d = { download_id: e["dlm-download-id"], version_id: e["dlm-version-id"], status: d, cookie: o, currentURL: r, action: "log_dlm_xhr_download", responseHeaders: e, nonce: dlmXHR.nonce }, jQuery.post(dlmXHR.ajaxUrl, d, function(e) { null !== t && (null == n && (n = "_self"), window.open(t, n)) })) } dlmNoAccessModal(e) { let d = "empty-download" , o = "empty-version" , t = "empty-restriction" , r = ""; void 0 !== e["dlm-download-id"] && (d = e["dlm-download-id"]), void 0 !== e["dlm-version-id"] && (o = e["dlm-version-id"]), void 0 !== e["dlm-no-access-modal-text"] && (r = e["dlm-no-access-modal-text"]), void 0 !== e["dlm-no-access-restriction"] && (t = e["dlm-no-access-restriction"]); const n = { download_id: d, version_id: o, modal_text: r, restriction: t, action: "no_access_dlm_xhr_download", nonce: dlmXHR.nonce }; jQuery.post(dlmXHR.ajaxUrl, n, function(e) { jQuery("#dlm-no-access-modal").remove(), jQuery("body").append(e), jQuery(document).trigger("dlm_no_access_modal_response", [e, n]) }) } dlmExternalDownload(e, t, r, n, l) { const a = new XMLHttpRequest , d = e["dlm-external-download"]; r.attr("target"); let s = r.attr("class"), i; s = void 0 !== s && "" !== s ? s.replace("dlm-download-started", "").replace("dlm-download-completed", "") : "", r.addClass("dlm-download-started"), t.setAttribute("href", "#"), t.removeAttribute("download"), t.setAttribute("disabled", "disabled"), jQuery(document).trigger("dlm_download_triggered", [this, t, r, i]), a.responseType = "blob", a.onreadystatechange = function() { var {status: e, readyState: d} = a , o = a.getAllResponseHeaders().split("\r\n").reduce((e,d)=>{ var [d,o] = d.split(": "); return e[d] = o, e } , {}); if (403 === e) return dlmXHRinstance.dlmLogDownload(o, "failed", !1), a.abort(), void r.append('<span class="dlm-xhr-error">Acces Denied to file.</span>'); 200 == e && 4 == d && (e = a.response, i = URL.createObjectURL(e), t.removeEventListener("click", dlmXHRinstance.handleDownloadClick), t.setAttribute("download", "" + n), t.setAttribute("href", i), t.click(), r.removeClass().addClass(s + " dlm-download-complete"), dlmXHRinstance.attachButtonEvent(), jQuery(document).trigger("dlm_download_complete", [this, t, r, i]), dlmXHRinstance.dlmLogDownload(o, "completed", !1), window.URL.revokeObjectURL(i), t.removeAttribute("download"), t.setAttribute("href", l), r.find(".dlm-xhr-loading-gif").remove(), setTimeout(function() { r.removeClass().addClass(s).find("span.dlm-xhr-progress").remove() }, 1e3)) } , a.addEventListener("progress", function(e) { let d = e.loaded / e.total * 100; d = d.toFixed(); var o; r.find("span.dlm-xhr-progress").remove(), o = "dlm-download-started download-" + 10 * Math.ceil(d / 10), 1 / 0 != d && r.append('<span class="dlm-xhr-progress"> ' + d + "%</span>"), r.removeClass().addClass(s + " " + o), jQuery(document).trigger("dlm_download_progress", [this, t, r, i, e, d]) }), a.onerror = function() { t.removeAttribute("download"), t.setAttribute("href", l), r.removeClass().addClass(s + " .dlm-no-xhr-download").find("span.dlm-xhr-progress").remove(), r.append('<span class="dlm-xhr-error">' + dlmXHRtranslations.error + "</span>"), console.log("** An error occurred during the transaction") } , a.open("GET", d, !0), a.setRequestHeader("dlm-xhr-request", "dlm_XMLHttpRequest"), a.send() } }
Triggering a File Download from an XHR Post Request
July 07, 2018 | 1 minute read
If you need your webapp to offer a file download for an asset created on the fly, like say a PDF generated from content entered by a user, how do you do that? This was a puzzle I encountered not too long ago on a personal proejct. I dug around and found a pretty solid solution, which I'll detail in this post.
Photo by Mandi Cai
The specific scenario in this personal project was that I needed to POST data from an HTML form to a server, and then trigger a download for the payload of the POST response. There might be a few reasons you would want to do this kind of trickery, but for me, I was generating a PDF on the server based on the contents of te POST request, and then returning that PDF to the client. The desired experience for the user is just a simple 'Download' button, so even though an asset is being dynamically generated, we want to give the illusion that they're just downloading.
The Request
Step one is to set up the XHR request in Javascript. For some context, let's imagine a simple HTML form:
<form id="form">
<input type="text"/>
<button type="submit" form="form">Generate Report</button>
</form>
When this form is submitted, we're going to send the form data to the server, and expect a PDF back in return, generated dynamically, which is where the responseType comes in.
let xhr = new XMLHttpRequest();
//set the request type to post and the destination url to '/convert'
xhr.open('POST', 'convert');
//set the reponse type to blob since that's what we're expecting back
xhr.responseType = 'blob';
let formData = new FormData(this);
xhr.send(formData);
What Is a Blob?
“A Blob object represents a file-like object of immutable, raw data. Blobs represent data that isn’t necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user’s system.” — MDN Web Docs: Blob
The Response
Great now that we've wired up the submission, let's take a bit of time to talk about what's happening on the server's side. I'm keeping this post backend agnostic, so I won't be discussing specific syntax. However, the basic mechanics are pretty simple. The server will accept the incoming POST request, and parse out the form data. It will then use that form data to generate some type of file, such as a PDF, represented in memory as Binary data. You'll pipe that binary data back to the user as the response to the POST request. Remember that on the client side, we've set the request to expect a Blob.
With that in mind, it's time to focus on what to do for the response. For this, we'll make use of the request's onload function.
xhr.onload = function(e) {
if (this.status == 200) {
// Create a new Blob object using the
//response data of the onload object
var blob = new Blob([this.response], {type: 'image/pdf'});
//Create a link element, hide it, direct
//it towards the blob, and then 'click' it programatically
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
//Create a DOMString representing the blob
//and point the link element towards it
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = 'myFile.pdf';
//programatically click the link to trigger the download
a.click();
//release the reference to the file by revoking the Object URL
window.URL.revokeObjectURL(url);
}else{
//deal with your error state here
}
};
All Together Now
Finally, let's combine all of this together into a single event listener that is fired with the form is submitted.
document.querySelector('#form').addEventListener('submit', (e)=>{
e.preventDefault();
let xhr = new XMLHttpRequest();
//set the request type to post and the destination url to '/convert'
xhr.open('POST', 'convert');
//set the reponse type to blob since that's what we're expecting back
xhr.responseType = 'blob';
let formData = new FormData(this);
xhr.send(formData);
xhr.onload = function(e) {
if (this.status == 200) {
// Create a new Blob object using the response data of the onload object
var blob = new Blob([this.response], {type: 'image/pdf'});
//Create a link element, hide it, direct it towards the blob, and then 'click' it programatically
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
//Create a DOMString representing the blob and point the link element towards it
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = 'myFile.pdf';
//programatically click the link to trigger the download
a.click();
//release the reference to the file by revoking the Object URL
window.URL.revokeObjectURL(url);
}else{
//deal with your error state here
}
};
});
南来地,北往的,上班的,下岗的,走过路过不要错过!
======================个性签名=====================
之前认为Apple 的iOS 设计的要比 Android 稳定,我错了吗?
下载的许多客户端程序/游戏程序,经常会Crash,是程序写的不好(内存泄漏?刚启动也会吗?)还是iOS本身的不稳定!!!
如果在Android手机中可以简单联接到ddms,就可以查看系统log,很容易看到程序为什么出错,在iPhone中如何得知呢?试试Organizer吧,分析一下Device logs,也许有用.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
2020-02-17 使用joda-time工具类 计算时间相差多少 天,小时,分钟,秒