Hope there hadn't any question same as mine.
I tried to write some share screen and screen record. For that I found others code to study.
In the code, it used the video filename extension is .webm. I tried to change it to .mp4 but failed.
I thought that video/webm and video/mp4 were both valid. But not know why, when I changed filename extension, it got worse.
Is there anything wrong I didn't find? I had tried some keywords to search (for example, video/webm mp4) but had no result. I would like to know if my keyword direction is wrong?
Thankyou.
The following is part of the code:
btnPlay.onclick = () => {
var blob = new Blob(buffer, { type: 'video/webm' })
recvideo.src = window.URL.createObjectURL(blob)
recvideo.srcObject = null
recvideo.controls = true
recvideo.play()
}
// download record
btnDownload.onclick = () => {
var blob = new Blob(buffer, { type: 'video/webm' })
var url = window.URL.createObjectURL(blob)
var a = document.createElement('a')
a.href = url
a.style.display = 'none'
a.download = 'video.webm'
a.click()
}
In the code, I only changed webm to mp4.
The code source: https://ithelp.ithome.com.tw/articles/10273368?sc=iThomeR
Related
Hi I am a beginner so I am not having much knowledge about javascript so kindly help me in solving my issue.
I am facing problem in saving audio input. The audio which is saved onto the disk is somehow corrupted and not proper (.mp3/.wav) file.
Here is my javascript code
function saveBlob(blob, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
function startRecording(){
var device = navigator.mediaDevices.getUserMedia({audio:true});
var items = [];
device.then( stream => {
var recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
items.push(e.data);
if(recorder.state == "inactive")
{
var blob = new Blob(items, {type: 'audio/wav'});
alert(blob.type);
saveBlob(blob, 'myRecording.wav');
}
}
recorder.start();
setTimeout(()=>{
recorder.stop();
}, 4000);
});
I think the problem is that you save the file with the wrong mimeType. As far as I know there is no browser which can record WAV files out of the box.
A quick fix would be to change the part which creates the file.
var blob = new Blob(items, {type: recorder.mimeType});
alert(blob.type);
saveBlob(blob, `myRecording.wav${blob.type.split('/')[1].split(';')[0]}`);
Or you could use a package like extendable-media-recorder which allows to record WAV files directly.
I have a POST call that returns a base64 PDF. When I call this endpoint I convert it to a Blob and then download it. This works fine in all browsers except for Safari.
openPdf = () => {
const sendObj = {
fakeValue: 'test'
};
axios.post('https://fakeendpoint.com/create-pdf', sendObj)
.then((res) => {
const base64URL = res.data;
const binary = atob(base64URL.replace(/\s/g, ''));
const len = binary.length;
const buffer = new ArrayBuffer(len);
const view = new Uint8Array(buffer);
for (let i = 0; i < len; i += 1) {
view[i] = binary.charCodeAt(i);
}
// create the blob object with content-type "application/pdf"
const blob = new Blob([view], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = 'Test.pdf';
a.target = '_blank';
a.click();
});
}
How can I get this to work in Safari?
Seems like Safari doesn't follow the standards for the a tag. I believe this previous SO post identifies the root cause. From the comments in the linked answer:
Note that specifying a target attribute in Safari seems to override the download attribute (this does not seem to be the case in Chrome, Firefox or Opera).
Try removing a.target = '_blank' in your code above and then testing it. It should work!
Unfortunately, I'm not sure how you would open it in a new tab with that change.
from a test I made - this occurs only when the PDF is too big. (and only on mobile Safari)
I assume it is related to the length of the URL.
The only drawback from removing target="_blank" is that if the user click on "back" it will loose the previous page state.
I have a saved .PDF file on my system, and I am trying to send the file to the frontend using node/express.
I'm getting the file to send to the frontend as a stream (binary string), but when running some code on the frontend to get the .PDF to download onto the users computer, the .PDF file shows up blank.
Here is my route on the server:
app.post('/someroute', (req, res) => {
let pdfPath = './somepath/where/the/pdf/is'
// if the file does not exist
if (!fs.existsSync(pdfPath)) {
console.log(`The PDF does NOT exist # ${pdfPath}`)
return res.json({ success: false });
}
res.download(pdfPath, (err) => {
if (err) {
console.log('there was error in res.downoad!', err)
} else {
fs.unlink(pdfPath, (err) => {
if (err) {
console.log('there was error in unlinking the pdf file!', err)
} else {
console.log('success!')
}
})
}
})
})
Here is the code on the frontend:
$.post("/someroute", function(data) {
console.log('creating PDF...', data)
var downloadLink = document.createElement('a')
downloadLink.target = '_blank'
downloadLink.download = 'new_pdf_haha.pdf'
var blob = new Blob([data], { type: 'application/pdf' })
var URL = window.URL || window.webkitURL
var downloadUrl = URL.createObjectURL(blob)
// set object URL as the anchor's href
downloadLink.href = downloadUrl
// append the anchor to document body
document.body.append(downloadLink)
// fire a click event on the anchor
downloadLink.click()
// cleanup: remove element and revoke object URL
document.body.removeChild(downloadLink)
URL.revokeObjectURL(downloadUrl)
})
Here is the stream i'm receiving on the frontend:
stream on the frontend
Here is the PDF i'm expecting to be downloaded on the frontend:
Here is what's actually being downloaded:
If anyone can lend any insight or help it would be very much appreciated, thanks!
I think the main reason this isn't working for you is because jQuery doesn't support the 'blob' data type.
I did some research and found an example of how to get this to work with jQuery:
http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/
You need to include the jQuery plugin from the blog post then convert your $.post call to a $.ajax call (with method POST) and specify that the transfer data type be 'binary' (to load the plugin).
After including the plugin, change your code to look like this:
$.ajax({
method: "POST",
url: "/someroute",
dataType: 'binary' // USE THE PLUGIN
})
.then(function (data) {
console.log("Got the PDF file!");
// Do with the PDF data as you please.
var downloadLink = document.createElement('a')
downloadLink.target = '_blank'
downloadLink.download = 'new_pdf_haha.pdf'
var blob = new Blob([data], { type: 'application/pdf' })
var URL = window.URL || window.webkitURL
var downloadUrl = URL.createObjectURL(blob)
downloadLink.href = downloadUrl
document.body.append(downloadLink) // THIS LINE ISN'T NECESSARY
downloadLink.click()
document.body.removeChild(downloadLink); // THIS LINE ISN'T NECESSARY
URL.revokeObjectURL(downloadUrl);
})
.catch(function (err) {
console.error("An error occurred.");
console.error(err);
});
There's a full working example for you here:
https://github.com/ashleydavis/pdf-server-example
Note that my server setup is different to yours, that may or may not be an issue for you. I have included example code for streaming and non-streaming PDF file download for comparison - streaming is used by default because I think that's what you wanted.
Also note that it does not appear necessary to add your synthesized link to the document and I have marked those lines as unnecessary.
I should also note that it is probably best to do this kind of thing with HTTP GET rather than HTTP POST. If you did that you could simplify your browser download code to be the following:
var downloadLink = document.createElement('a');
downloadLink.target = '_blank';
downloadLink.download = 'new_pdf_haha.pdf';
downloadLink.href = "someroute";
document.body.append(downloadLink)
downloadLink.click()
document.body.removeChild(downloadLink);
I'm currently working on fixing a CSV Export of a data table on a web application.
It's currently able to export on all needed browsers except Chrome when you click the export button.
I've been trying to figure it out for a while now and I'm resisting pulling my hair out.
The code below is my service that was working until recently. Any help is greatly appreciated.
svc.downloadContent =
(target, fileName, content) => {
if (!browserSvc.canDownloadFiles()) return;
// IE10
if (window.navigator.msSaveOrOpenBlob) {
const blob = new Blob([content], {type: 'text/csv'});
window.navigator.msSaveOrOpenBlob(blob, fileName);
// IE9
} else if (env.browser === 'Explorer') {
const frame = document.createElement('iframe');
document.body.appendChild(frame);
angular.element(frame).hide();
const cw = frame.contentWindow;
const cwDoc = cw.document;
cwDoc.open('text/csv', 'replace');
cwDoc.write(content);
cwDoc.close();
cw.focus();
cwDoc.execCommand('SaveAs', true, fileName);
document.body.removeChild(frame);
// Sane browsers
} else {
const blob = new Blob([content], {type: 'text/csv'});
const url = URL.createObjectURL(blob);
const a = angular.element(target);
const download = a.attr('download');
// If not already downloading ...
if (!download) {
a.attr('download', fileName);
a.attr('href', url);
// This must run in the next tick to avoid
// "$digest already in progress" error.
//$timeout(() => target.click());
try {
target.click();
// Clear attributes to prepare for next download.
a.attr('download', '');
a.attr('href', '');
} catch (e) {
console.error('csv-svc.js: e =', e);
}
}
}
I managed to figure this out just a couple minutes after posting my question. I needed to add an else if just for Chrome. However, I will post the fix and leave this up, in hopes that it may help someone else in the future.
else if (env.browser === 'Chrome') {
const blob = new Blob([content], {type: 'text/csv'});
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.style = 'visibility:hidden';
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
How can I make a browser display a "save as dialog" so the user can save the content of a string to a file on his system?
For example:
var myString = "my string with some stuff";
save_to_filesystem(myString,"myString.txt");
Resulting in something like this:
EDIT 2022: Please see other answers regarding File System API
In case anyone is still wondering...
I did it like this:
Save
can't remember my source but it uses the following techniques\features:
html5 download attribute
data URI's
Found the reference:
http://paxcel.net/blog/savedownload-file-using-html5-javascript-the-download-attribute-2/
EDIT:
As you can gather from the comments, this does NOT work in
Internet Explorer (however works in Edge v13 and later)
Opera Mini
http://caniuse.com/#feat=download
There is a new spec called the Native File System API that allows you to do this properly like this:
const result = await window.chooseFileSystemEntries({ type: "save-file" });
There is a demo here, but I believe it is using an origin trial so it may not work in your own website unless you sign up or enable a config flag, and it obviously only works in Chrome. If you're making an Electron app this might be an option though.
There is a javascript library for this, see FileSaver.js on Github
However the saveAs() function won't send pure string to the browser, you need to convert it to blob:
function data2blob(data, isBase64) {
var chars = "";
if (isBase64)
chars = atob(data);
else
chars = data;
var bytes = new Array(chars.length);
for (var i = 0; i < chars.length; i++) {
bytes[i] = chars.charCodeAt(i);
}
var blob = new Blob([new Uint8Array(bytes)]);
return blob;
}
and then call saveAs on the blob, as like:
var myString = "my string with some stuff";
saveAs( data2blob(myString), "myString.txt" );
Of course remember to include the above-mentioned javascript library on your webpage using <script src=FileSaver.js>
This is possible using this cross browser javascript implementation of the HTML5 saveAs function: https://github.com/koffsyrup/FileSaver.js
If all you want to do is save text then the above script works in all browsers(including all versions of IE), using nothing but JS.
Solution using only javascript
function saveFile(fileName,urlFile){
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
a.href = urlFile;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}
let textData = `El contenido del archivo
que sera descargado`;
let blobData = new Blob([textData], {type: "text/plain"});
let url = window.URL.createObjectURL(blobData);
//let url = "pathExample/localFile.png"; // LocalFileDownload
saveFile('archivo.txt',url);
Using showSaveFilePicker():
const handle = await showSaveFilePicker({
suggestedName: 'name.txt',
types: [{
description: 'Text file',
accept: {'text/plain': ['.txt']},
}],
});
const blob = new Blob(['Some text']);
const writableStream = await handle.createWritable();
await writableStream.write(blob);
await writableStream.close();
Inspired by #ronald-coarite answer, here is my solution:
function saveTxtToFile(fileName: string, textData: string) {
const blobData = new Blob([textData], { type: 'text/plain' });
const urlToBlob = window.URL.createObjectURL(blobData);
const a = document.createElement('a');
a.style.setProperty('display', 'none');
document.body.appendChild(a);
a.href = urlToBlob;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(urlToBlob);
a.remove();
}
saveTxtToFile('myFile.json', JSON.stringify(myJson));