最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Set file name and format if file or file location contains neither - Stack Overflow

programmeradmin1浏览0评论

I'd like to set the file name and format of a "non-typical file", for a lack of better words. The files are stored at locations such as the following...

let link = https://.../videoplayback?ipbits=0&initcwndb...D134213BA9465CB74DFD36CDE47BF.102638C4A9F3ACA357F79EE747DD5F49F1E0F0DE

When one downloads such files, even if they are pletely different files, they always end up being saved with the same name and never a file extension.

I've tried url.download = link + '.mp4', but this has no effect whatsoever.

How can I do this?

I'd like to set the file name and format of a "non-typical file", for a lack of better words. The files are stored at locations such as the following...

let link = https://.../videoplayback?ipbits=0&initcwndb...D134213BA9465CB74DFD36CDE47BF.102638C4A9F3ACA357F79EE747DD5F49F1E0F0DE

When one downloads such files, even if they are pletely different files, they always end up being saved with the same name and never a file extension.

I've tried url.download = link + '.mp4', but this has no effect whatsoever.

How can I do this?

Share Improve this question asked Jul 26, 2017 at 3:11 oldboyoldboy 5,9747 gold badges42 silver badges99 bronze badges 8
  • How are you sourcing the files? – TheChetan Commented Jul 28, 2017 at 8:13
  • @TheChetan downloading them off of the internet via the browser – oldboy Commented Jul 28, 2017 at 22:48
  • @Anthony Are the files served with CORS headers? – guest271314 Commented Jul 30, 2017 at 13:47
  • @guest271314 i have no idea. how would i even determine that? ajax or something? – oldboy Commented Aug 1, 2017 at 3:35
  • @Anthony Do you have control over the files? – guest271314 Commented Aug 1, 2017 at 3:38
 |  Show 3 more ments

3 Answers 3

Reset to default 6 +25

According to the MDN for anchor tags with the download attribute:

Can be used with blob: URLs and data: URLs, to make it easy for users to download content that is generated programmatically using JavaScript (e.g. a picture created using an online drawing Web app).

If the HTTP header Content-Disposition: is present and gives a different filename than this attribute, the HTTP header has priority over this attribute.

If this attribute is present and Content-Disposition: is set to inline, Firefox gives priority to Content-Disposition, like for the filename case, while Chrome gives priority to the download attribute.

This attribute is only honored for links to resources with the same-origin.

So if you are dynamically generating these links and they e from your own server - you can set the filename. A cross-origin request will not work!

You may be able use ajax to fetch the file as a blob and trick the browser into thinking that the data is not cross-origin. See this answer for one possible implementation.

One approach would be to perform a HEAD request before setting .download property of <a> element to determine the Content-Type of the requested resource, use a JSON string, JavaScript object or other key, value pair data storage format to reflect pairs of valid MIME types to valid file extensions corresponding to the MIME type property. Use .indexOf(), RegExp or other filtering method to determine if there is a match between the property name of the string or object and the value of the property, if true store the extension value and concatenate the extension to the suggested file name.

If the file is not served with CORS headers you can try using a proxy to make HEAD of GET request to get the Content-Type header before setting the .download attribute.

It should be noted that the .download attribute is only a suggestion to the user for the filename. The user can change the name of the file at any time, including deleting the file extension, for whatever reason they may or may not have. Or not download the resource at all.

const mimeTypeExtensions = {
  "text/plain": ".txt",
  "video/mp4": ".mp4",
  /* valid MIME types and corresponding extensions */
}

const a = document.querySelector("a");

a.addEventListener("click", event => {

  if (!a.download) {
  
    event.preventDefault();
    
    fetch(a.href, {method: "HEAD"})
    .then(response => {
      const mimeType = response.headers.get("content-type");
      let fileExtension = "";
      for (let [key, prop] of Object.entries(mimeTypeExtensions)) {
          if (key.indexOf(mimeType) > -1) {
            fileExtension = prop;
            break;
          };
       }
       a.download = `filename${fileExtension}`;
       a.click();
    })
    .catch(err => console.error(err))

  }

});
<a href="https://gist.githubusercontent./guest271314/11edc4566ba94f204dd46e6ae26edaad/raw/d118e99abbe2a2c60634e46816df9e1b9de6b6b8/D134213BA9465CB74DFD36CDE47BF102638C4A9F3ACA357F79EE747DD5F49F1E0F0DE">click</a>

Here is an easy option if you don't mind adding a library. FileSaver.js handles these cases well while hiding the ugly details. I was going to go into how you could create Blob, write the contents of the download into it, and then create an anchor tag with an Object URL created from the Blob, but FileSaver handles that already and you could look at the source if you really wanted.

Just modify the following to add some checks and logic for determining filename/filetype and you should be able to tackle your use case.

<script src="cdn-to-FileSaver.js"></script>

<script>
var url = ...;
fetch(url).then((response) => {
  var blob = response.blob();
  var filename = 'song.mp4';

  saveAs(blob, filename);
});
</script>
发布评论

评论列表(0)

  1. 暂无评论