使用方法

  • index.php填上你的 token 即可,

  • 然后打开index.html上传图片

获取token方法

  • 注册:https://czz.meituan.com/

  • 发布视频,上传封面,注意在上传封面后,F12查找封面 token 即可,不用真的去发布视频

特色

  • 可在任意位置粘贴图片

  • 粘贴图片直接触发上传

  • 上传成功后自动复制图片链接

图库功能

  • 数据仅保存在本地浏览器中,不同设备或浏览器之间无法共享

  • 如果用户清除浏览器数据,图库信息会丢失

部署在 Vercel 上

  • 目录结构

mtbed/
├── api/
│   ├── index.php
├── index.html
├── favicon.ico
└── vercel.json

项目代码备份

  • index.php

<?php
// ----------------------
// 作者:在意 zai1.com
// 来源:https://zai1.com/word/141.html
// 本仓库仅用于分享,之前不知道作者,现在才知道,特意加上作者的版权出处
// 作者要求随意转载,但需要保留出处
// 本仓库地址:https://github.com/zixiwu/mt-img-bed
// ----------------------
// 检查是否有文件上传
if(isset($_FILES['file'])) {
    // 获取文件信息
    $file = $_FILES['file'];
    // 设置请求头
    $headers = array(
        'Accept: */*',
        'Accept-Encoding: gzip, deflate, br',
        'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
        'Cache-Control: no-cache',
        'Connection: keep-alive',
        'Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywt1pMxJgab51elEB',
        'Host: pic-up.meituan.com',
        'Origin: https://czz.meituan.com',
        'Pragma: no-cache',
        'Referer: https://czz.meituan.com/',
        'Sec-Fetch-Dest: empty',
        'Sec-Fetch-Mode: cors',
        'Sec-Fetch-Site: same-site',
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0',
        'client-id: p5gfsvmw6qnwc45n000000000025bbf1',
        'sec-ch-ua: "Not A(Brand";v="99", "Microsoft Edge";v="121", "Chromium";v="121"',
        'sec-ch-ua-mobile: ?0',
        'sec-ch-ua-platform: "Windows"',
        'token: 这里填美团开放平台的token,在这里登陆获取即可czz.meituan.com'
    );
    // 构建 multipart/form-data 格式的数据
    $postData = "------WebKitFormBoundarywt1pMxJgab51elEB\r\n";
    $postData .= 'Content-Disposition: form-data; name="file"; filename="' . $file['name'] . "\"\r\n";
    $postData .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";
    $postData .= file_get_contents($file['tmp_name']) . "\r\n";
    $postData .= "------WebKitFormBoundarywt1pMxJgab51elEB--\r\n";
    // 初始化 cURL
    $ch = curl_init();
    // 设置 cURL 选项
    curl_setopt($ch, CURLOPT_URL, 'https://pic-up.meituan.com/extrastorage/new/video?isHttps=true');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    // 执行请求并获取响应
    $response = curl_exec($ch);
    // 检查是否有错误发生
    if(curl_errno($ch)){
        echo 'Curl error: ' . curl_error($ch);
        exit;
    }
    // 关闭 cURL 资源
    curl_close($ch);
    // 解析 JSON 响应
    $jsonResponse = json_decode($response, true);
    // 检查是否上传成功
    if(isset($jsonResponse['success']) && $jsonResponse['success'] === true) {
        // 提取原始链接和原始文件名
        $originalLink = $jsonResponse['data']['originalLink'];
        $originalFileName = $jsonResponse['data']['originalFileName'];
        
        // 组成新的 JSON 并输出
        $newJson = array(
            'Jobs' => $originalLink,
            'Name' => $originalFileName,
            'os'=>'node-oss.zai1.com'
        );
        echo json_encode($newJson);
    } else {
        // 输出上传失败信息
        echo json_encode(array('error' => 'Upload failed'));
    }
} else {
    echo "No file uploaded.";
}
?>
  • index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>美团CDN图床</title>
    <link rel="icon" href="favicon.ico" type="image/x-icon" />
    <style>
        body, html {
            height: 100%;
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
            background-color: #f0f4f8;
        }
        .container {
            background-color: #ffffff;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            text-align: center;
            width: 90%;
            max-width: 500px;
        }
        h2 {
            color: #2c3e50;
            margin-bottom: 1.5rem;
        }
        #uploadArea {
            border: 2px dashed #3498db;
            padding: 20px;
            margin-top: 1rem;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        #uploadArea:hover {
            background-color: #ecf0f1;
        }
        #fileInput {
            display: none;
        }
        #uploadBtn {
            background-color: #2ecc71;
            color: white;
            border: none;
            padding: 10px 20px;
            margin-top: 1rem;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        #uploadBtn:hover {
            background-color: #27ae60;
        }
        #previewImage {
            max-width: 100%;
            height: auto;
            margin-top: 1rem;
            display: none;
            margin-left: auto;
            margin-right: auto;
        }
        #uploadStatus {
            margin-top: 1rem;
            font-weight: bold;
        }
        #resultContainer {
            display: none;
            margin-top: 2rem;
            text-align: left;
        }
        .result-item {
            margin-bottom: 1rem;
        }
        .result-label {
            font-weight: bold;
            color: #34495e;
        }
        .result-value {
            word-break: break-all;
        }
        .copy-btn {
            background-color: #9b59b6;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 3px;
            cursor: pointer;
            font-size: 0.8rem;
            margin-left: 10px;
            transition: background-color 0.3s ease;
        }
        .copy-btn:hover {
            background-color: #8e44ad;
        }
        pre {
            background-color: #f1f1f1;
            padding: 10px;
            border-radius: 4px;
            overflow-x: auto;
        }
        code {
            font-family: 'Courier New', Courier, monospace;
        }
        #galleryBtn {
            position: fixed;
            top: 20px;
            right: 20px;
            background-color: #3498db;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        #galleryBtn:hover {
            background-color: #2980b9;
        }
        #galleryModal {
            display: none;
            position: fixed;
            z-index: 1;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0,0,0,0.4);
        }
        .modal-content {
            background-color: #fefefe;
            margin: 5% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 1200px;
            border-radius: 8px;
        }
        .close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
        }
        .close:hover,
        .close:focus {
            color: black;
            text-decoration: none;
            cursor: pointer;
        }
        #galleryGrid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 20px;
            padding: 20px;
        }
        .gallery-item {
            position: relative;
            overflow: hidden;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            transition: transform 0.3s ease;
        }
        .gallery-item:hover {
            transform: scale(1.05);
        }
        .gallery-item img {
            width: 100%;
            height: 200px;
            object-fit: cover;
        }
        .gallery-item .copy-url-btn {
            position: absolute;
            bottom: 10px;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(52, 152, 219, 0.8);
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        .gallery-item .copy-url-btn:hover {
            background-color: rgba(41, 128, 185, 1);
        }
    </style>
</head>
<body>
    <div class="container">
        <h2>优雅的图片上传</h2>
        <div id="uploadArea">
            点击或拖拽图片到此处上传
            <input type="file" id="fileInput" accept="image/*">
        </div>
        <img id="previewImage" alt="预览图片">
        <button id="uploadBtn">上传图片</button>
        <div id="uploadStatus"></div>
        <div id="resultContainer">
            <h3>上传结果</h3>
            <div class="result-item">
                <span class="result-label">图片链接:</span>
                <span class="result-value" id="imageUrl"></span>
                <button class="copy-btn" data-copy="imageUrl">复制链接</button>
            </div>
            <div class="result-item">
                <span class="result-label">Markdown:</span>
                <pre><code id="markdownCode"></code></pre>
                <button class="copy-btn" data-copy="markdownCode">复制 Markdown</button>
            </div>
        </div>
    </div>

    <button id="galleryBtn">图库</button>

    <div id="galleryModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <h2>历史图片</h2>
            <div id="galleryGrid"></div>
        </div>
    </div>

    <script>
        const uploadArea = document.getElementById('uploadArea');
        const fileInput = document.getElementById('fileInput');
        const previewImage = document.getElementById('previewImage');
        const uploadBtn = document.getElementById('uploadBtn');
        const uploadStatus = document.getElementById('uploadStatus');
        const resultContainer = document.getElementById('resultContainer');
        const galleryBtn = document.getElementById('galleryBtn');
        const galleryModal = document.getElementById('galleryModal');
        const closeBtn = document.getElementsByClassName('close')[0];
        const galleryGrid = document.getElementById('galleryGrid');

        // 点击上传区域触发文件选择
        uploadArea.addEventListener('click', () => fileInput.click());

        // 文件选择处理
        fileInput.addEventListener('change', handleFileSelect);

        // 拖拽处理
        uploadArea.addEventListener('dragover', (e) => {
            e.preventDefault();
            e.stopPropagation();
            uploadArea.style.backgroundColor = '#ecf0f1';
        });

        uploadArea.addEventListener('dragleave', (e) => {
            e.preventDefault();
            e.stopPropagation();
            uploadArea.style.backgroundColor = '';
        });

        uploadArea.addEventListener('drop', handleDrop);

        // 粘贴处理
        document.addEventListener('paste', handlePaste);

        // 上传按钮点击事件
        uploadBtn.addEventListener('click', uploadImage);

        // 回车键触发上传
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Enter' && previewImage.src) {
                uploadImage();
            }
        });

        function handleFileSelect(event) {
            const file = event.target.files[0];
            if (file) {
                processFile(file);
            }
        }

        function handleDrop(event) {
            event.preventDefault();
            event.stopPropagation();
            uploadArea.style.backgroundColor = '';
            const file = event.dataTransfer.files[0];
            if (file && file.type.startsWith('image/')) {
                processFile(file);
            }
        }

        function handlePaste(event) {
            const items = (event.clipboardData || event.originalEvent.clipboardData).items;
            for (const item of items) {
                if (item.type.indexOf('image') !== -1) {
                    const file = item.getAsFile();
                    processFile(file);
                    // 在处理完文件后立即触发上传
                    setTimeout(uploadImage, 100);  // 短暂延迟以确保预览图片已加载
                    break;
                }
            }
        }

        function processFile(file) {
            const reader = new FileReader();
            reader.onload = function(e) {
                previewImage.src = e.target.result;
                previewImage.style.display = 'block';
            }
            reader.readAsDataURL(file);
        }

        function uploadImage() {
            if (!previewImage.src) {
                uploadStatus.textContent = '请先选择或粘贴一张图片';
                return;
            }

            uploadStatus.textContent = '上传中...';
            
            const formData = new FormData();
            fetch(previewImage.src)
                .then(res => res.blob())
                .then(blob => {
                    const file = new File([blob], "image.jpg", { type: "image/jpeg" });
                    formData.append('file', file);

                    fetch('mt.php', {
                        method: 'POST',
                        body: formData
                    })
                    .then(response => response.json())
                    .then(data => {
                        uploadStatus.textContent = '上传成功!图片链接已自动复制到剪贴板。';
                        displayResult(data);
                        copyTextToClipboard(data.Jobs);
                        saveToLocalStorage(data);
                    })
                    .catch(error => {
                        console.error('上传错误:', error);
                        uploadStatus.textContent = '上传失败,请重试。';
                    });
                });
        }

        function displayResult(data) {
            document.getElementById('imageUrl').textContent = data.Jobs;
            document.getElementById('markdownCode').textContent = `![Image](${data.Jobs})`;
            resultContainer.style.display = 'block';
        }

        function copyTextToClipboard(text) {
            const textArea = document.createElement("textarea");
            textArea.value = text;
            document.body.appendChild(textArea);
            textArea.select();
            document.execCommand('copy');
            document.body.removeChild(textArea);
        }

        function saveToLocalStorage(data) {
            let images = JSON.parse(localStorage.getItem('uploadedImages')) || [];
            images.unshift(data);
            localStorage.setItem('uploadedImages', JSON.stringify(images));
        }

        galleryBtn.onclick = function() {
            galleryModal.style.display = "block";
            loadGallery();
        }

        closeBtn.onclick = function() {
            galleryModal.style.display = "none";
        }

        window.onclick = function(event) {
            if (event.target == galleryModal) {
                galleryModal.style.display = "none";
            }
        }

        function loadGallery() {
            const images = JSON.parse(localStorage.getItem('uploadedImages')) || [];
            galleryGrid.innerHTML = '';
            images.forEach(image => {
                const item = document.createElement('div');
                item.className = 'gallery-item';
                item.innerHTML = `
                    <img src="${image.Jobs}" alt="Uploaded Image">
                    <button class="copy-url-btn">复制链接</button>
                `;
                item.querySelector('.copy-url-btn').onclick = function() {
                    copyTextToClipboard(image.Jobs);
                    this.textContent = '已复制';
                    setTimeout(() => this.textContent = '复制链接', 2000);
                };
                galleryGrid.appendChild(item);
            });
        }

        document.addEventListener('click', function(e) {
            if (e.target.classList.contains('copy-btn')) {
                const textToCopy = document.getElementById(e.target.getAttribute('data-copy')).textContent;
                copyTextToClipboard(textToCopy);
                e.target.textContent = '已复制';
                setTimeout(() => e.target.textContent = '复制链接', 2000);
            }
        });
    </script>
</body>
</html>
  • vercel.json

{
  "functions": {
    "api/index.php": {
      "runtime": "vercel-php@0.7.1"
    }
  }
}