banner
AcoFork

AcoFork

LOVETOLOVE

Cloudflare R2作為網盤!Workers+R2無伺服器部署!

警告:R2 免費容量是 10G,Workers 免費訪問限制是每日 100 萬次,很容易被刷流量,請為你綁定的域名設置速率限制等限制手段以避免睡一晚上成為百萬負翁#

創建一個 R2 存儲桶#

  1. 不教了,簡單的雅痞。可見創建 R2 存儲桶

將 R2 與 Workers 連接起來#

  1. 不教了,簡單的雅痞。可見創建 Workers,連接 R2
  2. 將 Workers 代碼改為如下,設置一個目錄單獨存放要公開的文件,這裡是guest。代碼內嵌了 HTML,可自行更改:
export default {
  async fetch(request, env, ctx) {
    const bucket = env.MY_BUCKET;
    const rootDirectory = 'guest/';
    const url = new URL(request.url);
    
    // Helper function to get the current directory
    const getCurrentDirectory = (path) => {
      const cleanPath = path.replace(/^\/+|\/+$/g, '');
      return rootDirectory + cleanPath + (cleanPath ? '/' : '');
    };

    // Helper function to get parent directory
    const getParentDirectory = (path) => {
      const parts = path.split('/').filter(p => p);
      parts.pop();
      return '/' + parts.join('/');
    };

    // List files and folders in the current directory
    async function listDirectory(directory) {
      const objects = await bucket.list({ prefix: directory, delimiter: '/' });
      const items = new Set();

      for (const obj of objects.objects) {
        const relativePath = obj.key.slice(directory.length);
        if (relativePath) {
          items.add(relativePath.split('/')[0]);
        }
      }

      for (const prefix of objects.delimitedPrefixes) {
        const relativePath = prefix.slice(directory.length);
        if (relativePath) {
          items.add(relativePath.split('/')[0]);
        }
      }

      return Array.from(items).sort();
    }

    // Handle directory listing
    if (!url.pathname.startsWith('/download/')) {
      const currentDirectory = getCurrentDirectory(url.pathname);
      try {
        const items = await listDirectory(currentDirectory);

        let html = `
          <!DOCTYPE html>
          <html lang="en">
          <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>AcoFork R2 Files</title>
            <style>
              body, html {
                margin: 0;
                padding: 0;
                font-family: Arial, sans-serif;
                line-height: 1.6;
                height: 100%;
              }
              body {
                background-image: url('https://hrandom.onani.cn');
                background-size: cover;
                background-position: center;
                background-attachment: fixed;
                display: flex;
                justify-content: center;
                align-items: center;
              }
              .container {
                width: 80%;
                max-width: 800px;
                margin: 40px;
                padding: 30px;
                background-color: rgba(255, 255, 255, 0.5);
                backdrop-filter: blur(10px);
                border-radius: 15px;
                box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
              }
              h1 {
                color: #333;
                text-align: center;
                margin-bottom: 30px;
              }
              ul {
                list-style-type: none;
                padding: 0;
                margin: 0;
              }
              li {
                margin-bottom: 10px;
                border: 1px solid rgba(0, 0, 0, 0.1);
                border-radius: 8px;
                overflow: hidden;
                transition: all 0.3s ease;
              }
              li:hover {
                transform: translateY(-3px);
                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
              }
              a {
                display: block;
                padding: 12px 15px;
                text-decoration: none;
                color: #333;
                transition: background-color 0.3s ease;
              }
              a:hover {
                background-color: rgba(255, 255, 255, 0.5);
              }
              .folder::before {
                content: "📁 ";
                color: #FFA500;
              }
              .file::before {
                content: "📄 ";
                color: #008000;
              }
              .parent-link {
                display: inline-block;
                margin-bottom: 20px;
                padding: 8px 15px;
                background-color: rgba(0, 102, 204, 0.8);
                color: white;
                text-decoration: none;
                border-radius: 5px;
                transition: background-color 0.3s ease;
              }
              .parent-link:hover {
                background-color: rgba(0, 82, 163, 0.9);
              }
              @keyframes clickEffect {
                0% { transform: scale(1); }
                50% { transform: scale(0.95); }
                100% { transform: scale(1); }
              }
              .click-effect {
                animation: clickEffect 0.3s;
              }
            </style>
          </head>
          <body>
            <div class="container">
              <h1>我的 R2 Files</h1>
        `;
        
        // Add parent directory link if not in root
        if (currentDirectory !== rootDirectory) {
          const parentDir = getParentDirectory(url.pathname);
          html += `<a href="${parentDir}" class="parent-link">&larr; 上級目錄</a>`;
        }
        
        html += '<ul>';
        for (const item of items) {
          const itemPath = currentDirectory.slice(rootDirectory.length) + item;
          const isFolder = !item.includes('.');
          const className = isFolder ? 'folder' : 'file';

          // Update href for files to use the external download URL
          const href = isFolder 
            ? `/${encodeURIComponent(itemPath)}` 
            : `https://r2-dl.afo.im/guest/${encodeURIComponent(itemPath)}`;

          html += `<li class="${className}"><a href="${href}" onclick="this.classList.add('click-effect'); setTimeout(() => this.classList.remove('click-effect'), 300);">${item}${isFolder ? '/' : ''}</a></li>`;
        }
        html += `
              </ul>
            </div>
            <script>
              document.addEventListener('DOMContentLoaded', (event) => {
                document.querySelectorAll('a').forEach(link => {
                  link.addEventListener('click', function(e) {
                    if (!this.classList.contains('parent-link')) {
                      e.preventDefault();
                      this.classList.add('click-effect');
                      setTimeout(() => {
                        window.location = this.href;
                      }, 300);
                    }
                  });
                });
              });
            </script>
          </body>
          </html>`;
          
        return new Response(html, {
          headers: { 'Content-Type': 'text/html; charset=utf-8' },
        });
      } catch (error) {
        console.error('Error listing objects:', error);
        return new Response('列出對象時出錯', { status: 500 });
      }
    }

    // Default response for any other invalid requests
    return new Response('無效請求', { status: 400 });
  },
};
  1. 如何上傳文件見為你的存儲桶添加文件
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。