I need to download files through multiple streams in browser. I run the php server which is able to process Range Requests, so it returns the number of bytes requested. But how to download parts of file in multiple streams to then combine them in one is a question. I do have control over requests.
Just combine them together, here is code sample:
var part1, part2
function rangeRequest1() {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", "http://localhost:3000/zuckjet.pdf", true);
xmlHttp.responseType = "blob";
xmlHttp.setRequestHeader("Range", "bytes=0-18000");
xmlHttp.onload = function() {
part1 = new Blob([oReq.response], {
type: 'application/pdf'
});
// Pseudocode: part2 = another rangeRequest's response
download()
};
function download() {
var link = document.createElement('a');
var blob = new Blob([part1, part2]);
link.download = 'zuckjet.pdf';
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(blob);
}
Related
I am coding youtube video downloader chrome extension. But youtube has separated mp4 and mp3. How can I combine the audio file and image file I received in blob type and turn it into a video with sound?
async function downloadFile(urlToSend) {
return new Promise(resolve => {
var req = new XMLHttpRequest();
req.open("GET", urlToSend, true);
req.responseType = "blob";
req.onload = function (event) {
// var blob = req.response;
// var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
// var link = document.createElement('a');
// link.href = window.URL.createObjectURL(blob);
resolve(req.response)
};
req.send();
})
};
async function zfc() {
var v = await downloadFile('/videoplayback.mp4')
var a = await downloadFile('/videoplayback.weba')
let newBlob = new Blob([v, a], { type: 'video/mp4' })
var as = document.createElement('a')
as.href = window.URL.createObjectURL(newBlob)
as.download = window.URL.createObjectURL(newBlob)
console.log(as)
console.log(newBlob)
// as.click()
var c = document.createElement('video')
c.src = window.URL.createObjectURL(newBlob)
document.body.appendChild(c)
}
zfc()
I tried merging with new blob but the video still has no sound. Can you please help?
Example video link:
https://rr7---sn-u0g3uxax3-xncs.googlevideo.com/videoplayback?expire=1641956798&ei=XvHdYbG8MI2qx_AP14yRoAQ&ip=95.2.13.77&id=o-APHbyEMFJZdr7FwyLDOkQWqycmDmo9oy8bSvx7qP4z-P&itag=313&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C271%2C278%2C313&source=youtube&requiressl=yes&mh=YY&mm=31%2C29&mn=sn-u0g3uxax3-xncs%2Csn-hgn7yn76&ms=au%2Crdu&mv=m&mvi=7&pl=21&initcwndbps=88750&vprv=1&mime=video%2Fwebm&ns=O-4SxebNzTxani0g_ScQEtMG&gir=yes&clen=589586219&dur=347.800&lmt=1638064072881015&mt=1641934876&fvip=2&keepalive=yes&fexp=24001373%2C24007246&c=WEB&txp=4532434&n=hBnxjZJEX82hOJ&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&sig=AOq0QJ8wRQIhAIu0SR_UsiQyUpJIkL_erKc_dElHk-1rwJMCI1486YaSAiBkH4jg8WHzRvEDsxnTTheBM_f1KsBFzqLiIUFJAIKh5w%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgapuFt6YijG3nAVfbULkJq2_uAwcjOnZpd0ZNUo1h5NMCIGgJh22ksRMeMOUkhhQUlRapjqa4DhVv-KfcfnYhkW8l
Example sound link:
https://rr7---sn-u0g3uxax3-xncs.googlevideo.com/videoplayback?expire=1641956798&ei=XvHdYbG8MI2qx_AP14yRoAQ&ip=95.2.13.77&id=o-APHbyEMFJZdr7FwyLDOkQWqycmDmo9oy8bSvx7qP4z-P&itag=251&source=youtube&requiressl=yes&mh=YY&mm=31%2C29&mn=sn-u0g3uxax3-xncs%2Csn-hgn7yn76&ms=au%2Crdu&mv=m&mvi=7&pl=21&initcwndbps=88750&vprv=1&mime=audio%2Fwebm&ns=O-4SxebNzTxani0g_ScQEtMG&gir=yes&clen=5822955&dur=347.821&lmt=1638059244799001&mt=1641934876&fvip=2&keepalive=yes&fexp=24001373%2C24007246&c=WEB&txp=4532434&n=hBnxjZJEX82hOJ&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&sig=AOq0QJ8wRQIgaqKAjgRHlNms4IMVKwGJmRb2DOl7slWujc2OeIqIlSkCIQDvVhAPmxgLg0g2WvrgjB0iNNnCyDbyRQQvu5ODx4PLXA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgapuFt6YijG3nAVfbULkJq2_uAwcjOnZpd0ZNUo1h5NMCIGgJh22ksRMeMOUkhhQUlRapjqa4DhVv-KfcfnYhkW8l
I am also currently working on a YouTube video downloader extension for Firefox. If you are using ytdl-core, the response object contains a link that has both in res.player_response.streaming_data.formats[0]. However, there is only one such link, which doesn't allow for users to select their preferred resolution, so being able to merge the two would be extremely helpful.
Also if you are using youtube-dl or anything similar to such the response object should be the same or very similar to ytdl-core's
I don't want to use this way(link)
because I don't want to open new window for file selection.
I just want to load & read excel file when I click some button.
But this is not work.. help me to load the excel file.
MYCODE:
const FILE_NAME = "C:/Users/A/project_list.xlsx";
function LoadSpread(json) {
jsonData = json;
workbook.fromJSON(json);
workbook.setActiveSheet("Revenues (Sales)");
}
function excelExport(fileName) {
console.log(fileName);
var excelUrl = fileName;
var oReq = new XMLHttpRequest();
oReq.open("get", excelUrl, true);
oReq.responseType = "blob";
oReq.onload = function() {
var blob = oReq.response;
excelIO.open(blob, LoadSpread, function(message) {
console.log(message);
});
};
oReq.send(null);
}
function chkPrtNum(event) {
var fileName = FILE_NAME;
excelExport(fileName);
}
Try creating a small server for the same, you will easily get your job done. – Raghu Chahar Jan 28 at 9:50
This was very helpful
I am trying to attach an attachment through the composeView object using Inboxsdk. I obtain a blob object from a remote url using the following code.
// FUNCTION TO OPEN A NEW COMPOSE BOX ONCE THE ATTACHMENT BLOB IS OBTAINED FROM REMOTE URL.
function openComposeBox(sdk, blob){
handler = sdk.Compose.registerComposeViewHandler(function(composeView){
if(blob != null){
composeView.attachFiles([blob]);
composeView.setSubject("Testing");
}
});
}
// FETCHING ATTACHMENT FILE FROM REMOTE URL
var file_btn_url = "https://api.hummingbill.com/system/invoices/invoice_files/000/033/393/original/abracadabra.txt";
var file_name = file_btn_url.split("/");
file_name = file_name[file_name.length-1];
file_type = /[^.]+$/.exec(file_name);
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", file_btn_url);
xhr.responseType = "blob";
xhr.onload = function()
{
blob = xhr.response;
// blob.lastModifiedDate = new Date(); // Since it's not necessary to have it assigned, hence commented.
blob.name = file_name;
console.log(blob);
openComposeBox(sdk, blob);
}
xhr.send();
It shows an Attachment Failed error.
Although I have the correct format of blob object as required as per the documentation.
As per the documentation, I have set the filename for the blob, and passed it in an array to attachFiles function. Can you please look into it and let me know what am I missing?
Posting the solution. The code remains same as in the question, with a slight variation, wherein we convert the blob to a file, in order to make it work.
//... Same as the code in the question
// Fetching attachment file from remote url
var file_btn_url = "https://api.hummingbill.com/system/invoices/invoice_files/000/033/393/original/abracadabra.txt";
var file_name = file_btn_url.split("/");
file_name = file_name[file_name.length-1];
file_type = /[^.]+$/.exec(file_name);
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", file_btn_url);
xhr.responseType = "blob";
xhr.onload = function()
{
// Solution: Convert the obtained blob to a file
// Pass the file to openComposeBox
blob = new Blob([xhr.response], { type: xhr.responseType });
var file = new File([blob], file_name);
blob.name = file_name;
openComposeBox(sdk, file);
}
xhr.send();
Hope this helps. Cheers!
I have a web service that returns PDF file content in its response. I want to download this as a pdf file when user clicks the link. The javascript code that I have written in UI is as follows:
$http.get('http://MyPdfFileAPIstreamURl').then(function(response){
var blob=new File([response],'myBill.pdf',{type: "text/pdf"});
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="myBill.pdf";
link.click();
});
'response' contains the PDF byte array from servlet outputstream of 'MyPdfFileAPIstreamURl'. And also the stream is not encrypted.
So when I click the link, a PDF file gets downloaded successfully of size around 200KB. But when I open this file, it opens up with blank pages. The starting content of the downloaded pdf file is in the image.
I can't understand what is wrong here. Help !
This is the downloaded pdf file starting contents:
solved it via XMLHttpRequest and xhr.responseType = 'arraybuffer';
code:
var xhr = new XMLHttpRequest();
xhr.open('GET', './api/exportdoc/report_'+id, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var blob=new Blob([this.response], {type:"application/pdf"});
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="Report_"+new Date()+".pdf";
link.click();
}
};
xhr.send();
i fetched the data from server as string(which is base64 encoded to string) and then on client side i decoded it to base64 and then to array buffer.
Sample code
function solution1(base64Data) {
var arrBuffer = base64ToArrayBuffer(base64Data);
// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
var newBlob = new Blob([arrBuffer], { type: "application/pdf" });
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
// For other browsers:
// Create a link pointing to the ObjectURL containing the blob.
var data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
document.body.appendChild(link); //required in FF, optional for Chrome
link.href = data;
link.download = "file.pdf";
link.click();
window.URL.revokeObjectURL(data);
link.remove();
}
function base64ToArrayBuffer(data) {
var binaryString = window.atob(data);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
};
I was facing the same problem in my React project.
On the API I was using res.download() of express to attach the PDF file in the response. By doing that, I was receiving a string based file. That was the real reason why the file was opening blank or corrupted.
In my case the solution was to force the responseType to 'blob'. Since I was making the request via axios, I just simply added this attr in the option object:
axios.get('your_api_url_here', { responseType: 'blob' })
After, to make the download happen, you can do something like this in your 'fetchFile' method:
const response = await youtServiceHere.fetchFile(id)
const pdfBlob = new Blob([response.data], { type: "application/pdf" })
const blobUrl = window.URL.createObjectURL(pdfBlob)
const link = document.createElement('a')
link.href = blobUrl
link.setAttribute('download', customNameIfYouWantHere)
link.click();
link.remove();
URL.revokeObjectURL(blobUrl);
solved it thanks to rom5jp but adding the sample code for golang and nextjs
in golang using with gingonic context
c.Header("Content-Description", "File-Transfer")
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Content-Disposition","attachment; filename="+fileName)
c.Header("Content-Type", "application/pdf; charset=utf-8")
c.File(targetPath)
//c.FileAttachment(targetPath,fileName)
os.RemoveAll(targetPath)
in next js
const convertToPDF = (res) => {
const uuid = generateUUID();
var a = document.createElement('a');
var url = window.URL.createObjectURL(new Blob([res],{type: "application/pdf"}));
a.href = url;
a.download = 'report.pdf';
a.click();
window.URL.revokeObjectURL(url);
}
const convertFile = async() => {
axios.post('http://localhost:80/fileconverter/upload', {
"token_id" : cookies.access_token,
"request_type" : 1,
"url" : url
},{
responseType: 'blob'
}).then((res)=>{
convertToPDF(res.data)
}, (err) => {
console.log(err)
})
}
I was able to get this working with fetch using response.blob()
fetch(url)
.then((response) => response.blob())
.then((response) => {
const blob = new Blob([response], {type: 'application/pdf'});
const link = document.createElement('a');
link.download = 'some.pdf';
link.href = URL.createObjectURL(blob);
link.click();
});
Changing the request from POST to GET fixed it for me
I need to embed a Flash .swf on the page and am unable use the normal way of setting the src or data attribute to the swf url - don't ask :s. So, I'm doing an ajax request for the swf, converting to a blob and then generating a blob url which I set as the swf src. Then I realised that as I'm building with Grunt, there may be a way to just write the swf file into the code as a blob in a var, and avoid the ajax request completely. Here's the code with the ajax request:
function createFlashMovie(blobUrl){
var obj = document.createElement("object");
obj.setAttribute("width", "800");
obj.setAttribute("height", "600");
obj.setAttribute("type", "application/x-shockwave-flash");
obj.setAttribute("data", blobUrl);
document.body.appendChild(obj);
}
function onAjaxLoad(oResponse){
blobUrl = window.URL.createObjectURL(oResponse);
createFlashMovie(blobUrl);
};
//do the xhr request for a.swf
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200){
onAjaxLoad(this.response);
}
}
xhr.open('GET', '//theserver.com/a.swf');
xhr.responseType = 'blob';
xhr.send();
...but I'm sure it must be possible to have something like this which is replaced by grunt to have the blob already available when it runs, and go straight to creating the blob url without the xhr request:
var theBlob = new Blob(["GRUNT_WRITES_THIS_IN_FROM_FILE"], {type: "application/x-shockwave-flash"});
Well, grunt is at its core just a Node program, so you can use any node command in your Gruntfile or tasks definitions. And it seems that Node's http.request would be perfect for your needs.
So:
add a custom task in your Gruntfile (http://gruntjs.com/creating-tasks#custom-tasks)
that uses http.request to download your swf (https://docs.nodejitsu.com/articles/HTTP/clients/how-to-create-a-HTTP-request)
update your code to use the local swf
I found a solution. Convert your swf file to be a base64-encoded string. At the moment I'm doing this separately and then pasting it into the source JS, but it can be automated at build time with grunt. Then in the page script create a var to store it as a dataURI:
var swfAsDataUri = "data:application/x-shockwave-flash;base64,BIG_LONG_CHUNK_OF_DATA_THAT_IS_YOUR_ENCODED_SWF_FILE__GRUNT_CAN_WRITE_THIS_IN_AT_BUILD_TIME";
Create a blob from the data url, and then create an object url from the blob:
//function taken from http://stackoverflow.com/questions/27159179/how-to-convert-blob-to-file-in-javascript
dataURLToBlob = function(dataURL) {
var BASE64_MARKER = ';base64,';
var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {type: contentType});
};
var blobUrl = window.URL.createObjectURL( dataURLToBlob(swfAsDataUri) );
You can then use the object url as the src data for the flash movie's object tag when it's embedded:
function createFlashMovie(blobUrl){
var obj = document.createElement("object");
obj.setAttribute("width", "800");
obj.setAttribute("height", "600");
obj.setAttribute("type", "application/x-shockwave-flash");
obj.setAttribute("data", blobUrl); //use the object url here
document.body.appendChild(obj);
}
...and there you have it, no additional http request for the swf file.