2017-07-26 55 views
7

我想设置“非典型文件”的文件名和格式,缺少更好的单词。这些文件存储在诸如以下位置...设置文件名和格式,如果文件或文件位置都不包含

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

当一个下载这些文件,即使它们是完全不同的文件,他们总是最终被保存在相同的名字,从来没有一个文件延期。我试过url.download = link + '.mp4',但这没有任何效果。

我该怎么做?

+0

您是如何采购这些文件的? – TheChetan

+0

@TheChetan通过浏览器从互联网下载它们 – Anthony

+0

@Anthony这些文件是否以'CORS'标头提供? – guest271314

回答

6

按照MDN为anchor tags下载属性:

可与BLOB一起使用:URL和数据:网址,使用户轻松 来下载使用产生的程序内容 JavaScript(例如使用在线绘图Web应用程序创建的图片)。

如果HTTP头Content-Disposition:存在,并给出与此属性不同的文件名 ,则HTTP头优先于此属性的 。

如果此属性存在且Content-Disposition:内联处理设置为 ,则Firefox会优先处理Content-Disposition,如 文件名的情况,而Chrome会优先考虑download属性。

该属性仅适用于链接资源与 同源。

所以,如果你是动态生成这些链接,他们来自你自己的服务器 - 你可以设置文件名。 交叉来源请求不起作用!

您可能会使用ajax将文件作为blob获取并诱使浏览器认为数据不是交叉源。有关一种可能的实现,请参阅this answer

+0

一些示例代码? – Anthony

+0

在localhost/jsfiddle中尝试这种方法 - 单独下载attr不起作用。我认为它与localhost不作为服务器。可能在Apache上工作,但我不想这样做,以防你在本地设置它。这个解决方法修复了它:https://gist.github.com/nelsonkhan/7d4e4b5c2f6898cf6a40bc12a236cbbb – Kwestion

+0

以上将很可能在较新的浏览器上工作,但IE支持是一个已知的问题。我不确定在移动浏览器上 - 我无法在任何地方找到兼容性信息... – Kwestion

3

一种方法是设定<a>元件的.download属性来确定所请求的资源的Content-Type,使用JSON串,JavaScript对象或其他键,值对数据存储格式,以反映对有效之前执行HEAD请求MIME类型转换为对应于MIME类型属性的有效文件扩展名。使用.indexOf(),RegExp或其他筛选方法确定字符串或对象的属性名称与属性的值是否匹配,如果为true,则存储扩展名并将扩展名连接到建议的文件名。

如果文件不与CORS头服了你可以尝试使用代理进行HEADGET要求设置.download属性之前得到Content-Type头。

应该注意的是,.download属性只是向用户提供文件名的建议。用户可以随时更改文件的名称,包括删除文件扩展名,无论出于何种原因。或根本不下载资源。

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.com/guest271314/11edc4566ba94f204dd46e6ae26edaad/raw/d118e99abbe2a2c60634e46816df9e1b9de6b6b8/D134213BA9465CB74DFD36CDE47BF102638C4A9F3ACA357F79EE747DD5F49F1E0F0DE">click</a>

+0

当我得到一些时间时,我将不得不重读这个。你能详细阐述一下“......使用代理来使'GET'的'HEAD'请求...”。我想我明白你的意思,但措辞很难理解 – Anthony

2

下面是一个简单的选择,如果你不介意添加库。 FileSaver.js很好地处理这些案件,同时隐藏丑陋的细节。我将介绍如何创建Blob,将下载的内容写入其中,然后使用Blob创建的Object URL创建一个锚标记,但FileSaver已经处理了这些内容,并且您可以查看源代码真的很想。

只需修改以下内容即可添加一些用于确定文件名/文件类型的检查和逻辑,并且您应该能够解决您的使用案例。

<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

我会确定,当我有空闲时间的时候 – Anthony