图片点击下载而非预览

实现点击图片链接触发下载,而不是在浏览器中打开预览

问题

网站中的图片链接,点击后浏览器默认会打开预览。如何让用户点击后直接触发下载?

解答

方案一:使用 download 属性(同源)

<!-- download 属性可指定下载文件名 -->
<a href="/images/photo.jpg" download="my-photo.jpg">下载图片</a>

<!-- 不指定文件名,使用原文件名 -->
<a href="/images/photo.jpg" download>下载图片</a>

注意download 属性仅对同源 URL 有效,跨域资源会被忽略。

方案二:Blob 下载(支持跨域)

/**
 * 下载图片
 * @param {string} url - 图片地址
 * @param {string} filename - 保存的文件名
 */
async function downloadImage(url, filename) {
  try {
    // 获取图片数据
    const response = await fetch(url);
    const blob = await response.blob();
    
    // 创建 Blob URL
    const blobUrl = URL.createObjectURL(blob);
    
    // 创建隐藏的 a 标签并触发点击
    const link = document.createElement('a');
    link.href = blobUrl;
    link.download = filename;
    link.click();
    
    // 释放 Blob URL
    URL.revokeObjectURL(blobUrl);
  } catch (error) {
    console.error('下载失败:', error);
  }
}

// 使用示例
downloadImage('https://example.com/photo.jpg', 'photo.jpg');

方案三:服务端设置响应头

# Nginx 配置
location /downloads/ {
    add_header Content-Disposition "attachment";
}
// Node.js Express
app.get('/download/:filename', (req, res) => {
  const file = `./images/${req.params.filename}`;
  res.download(file); // 自动设置 Content-Disposition: attachment
});

完整组件示例

<!DOCTYPE html>
<html>
<body>
  <button onclick="download()">下载图片</button>

  <script>
    function download() {
      const url = 'https://picsum.photos/200/300';
      const filename = `image-${Date.now()}.jpg`;
      
      fetch(url)
        .then(res => res.blob())
        .then(blob => {
          const a = document.createElement('a');
          a.href = URL.createObjectURL(blob);
          a.download = filename;
          a.click();
          URL.revokeObjectURL(a.href);
        });
    }
  </script>
</body>
</html>

关键点

  • download 属性只对同源资源有效,跨域会失效
  • 跨域下载需要先 fetch 获取 blob,再通过 blob URL 下载
  • 使用后记得调用 URL.revokeObjectURL() 释放内存
  • 服务端可通过 Content-Disposition: attachment 响应头强制下载
  • 跨域 fetch 需要服务端配置 CORS