3

When you have a direct link to a video you can usually right click and the mouse menu will appear. Once there you'll see Save Video As. If you click on that it will download the video to your computer.

I want the same functionality but instead I want to make a button on an HTML page that when you click will do the exact same thing as mentioned above.

How can I do this?

Let's look at this example: I have this link: https://invidious.fdn.fr/latest_version?id=NF_69Dyle1Y&raw&itag=22

If you go on there and right click on the video you'll see this: example video with right click menu

Clicking on "Save Video As" you get: enter image description here

Which is a dialog for saving the video in your local storage.

Now my question is I want to do all this with a click of an html button. I want the dialog for saving to open without having to go on the video itself and right click and so on. Is there a way to do that?

the html a tag download attribute does not work. I've tried using URI like this

<a href='"data:application/octet-stream,"+encodeURIComponent(`https://invidious.fdn.fr/latest_version?id=NF_69Dyle1Y&raw&itag=22`)' download="video.mp4">download video</a>

but it also doesn't work.

BreezeWind
  • 528
  • 7
  • 16
  • Would one of these links answer your question? https://stackoverflow.com/questions/11336663/how-to-make-a-browser-display-a-save-as-dialog-so-the-user-can-save-the-conten https://stackoverflow.com/questions/2897619/using-html5-javascript-to-generate-and-save-a-file https://stackoverflow.com/questions/18690450/how-to-generate-and-prompt-to-save-a-file-from-content-in-the-client-browser – Invizio May 27 '20 at 15:38
  • no the download attribute does not work. – BreezeWind May 27 '20 at 15:39
  • (That's only one of the three links; the second one uses a data URI and the third uses a blob) – Invizio May 27 '20 at 15:43
  • Please give me some time to check them before closing my question. – BreezeWind May 27 '20 at 15:43
  • Don't worry, I'm not doing anything (Not even sure I'd have that power since I'm rather new on SO). In the case none of the other links work, please provide details about what you tried and what were the results. – Invizio May 27 '20 at 15:46
  • I've tried what is being said on the other links and I'm still stuck. I'll we try to edit my question to be more clear about what I want. – BreezeWind May 27 '20 at 16:11
  • (Ah, I see you are a man of culture as well - I know that Youtuber) I see what the problem is - basically, you're trying to execute JS code directly in the `href`, which isn't possible. I'll post the details (with a fix) in an answer shortly. – Invizio May 27 '20 at 17:08
  • thank you in advance! – BreezeWind May 27 '20 at 17:10

1 Answers1

5

If your video is located on the same origin as your webpage (not your case)

<a href="/path/to/video.mp4" download="video">Download</a>

Rather simple, does not require Javascript, and works on every browser except IE.


If your video is from a different origin (your case)

When testing my solution, I found out that cross-origin downloads are blocked by Chrome and Firefox for security purposes.

a. If you control the server

If the server implements proprer CORS, or if you have control over the server and can add those CORS, you can use this script that I shamelessly took from this SO question :

<!-- The style="display:none;" is optional, you can remove it if you don't want the feature explained below. -->
<a id="download-link" href="javascript:alert('The video is not yet ready!')" download="video" style="display:none;">Download</a>
<script>

var a = document.getElementById("download-link");

function downloadResource(url, filename) {

  // Current blob size limit is around 500MB for browsers
  if (!filename) filename = url.split('\\').pop().split('/').pop();
  fetch(url, {
      headers: new Headers({
        'Origin': location.origin
      }),
      mode: 'cors'
    })
    .then(response => response.blob())
    .then(blob => {
      let blobUrl = window.URL.createObjectURL(blob);

      // Place the resource in the href of the link
      a.href = blob;

      // Bonus : Only show the link if and when the Javascript code has executed
      a.style.display = "inline";
    })
    .catch(e => console.error(e));

}

downloadResource("https://invidious.fdn.fr/latest_version?id=NF_69Dyle1Y&raw&itag=22");

</script>

I added a little feature that will keep the link hidden until the file is completely downloaded. You can of course change this depending on your requirements.

b. If you don't control the server

If it uses CORS and allows all origins (or at least your origin), the script above should work.

If it doesn't, you're out of luck, sadly. You can still open the video in a new window and tell the user to right-click and "Save As" manually; it's less neat, but at least it works.

Invizio
  • 214
  • 1
  • 8