admin 管理员组

文章数量: 887017

使用 HTML 和 JavaScript 实现文件上传功能

1. 简介

在现代 web 开发中,实现文件上传功能是一个常见的需求。本文将介绍如何使用 HTML、CSS 和 JavaScript 创建一个支持 .obj.jpg 文件上传的网页应用,并且展示上传进度以及上传完成后的文件信息。用户可以逐个选择文件并上传,最后将上传成功的文件信息通过 JSON 发送到服务器。页面效果:

2. 开发环境

  • HTML5
  • CSS3
  • JavaScript (ES6)

3. 对话过程

我们从基础的文件上传功能开始,逐步改进页面的用户界面和功能,实现选择文件、显示进度、上传文件、展示上传结果等功能。以下是最终的 HTML、CSS 和 JavaScript 代码。

HTML 文件 (index.html)

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件上传</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="uploadContainer">
        <label for="fileInput">选择文件:</label>
        <input type="file" id="fileInput" multiple>
        <button id="uploadButton">上传文件</button>
        <div id="progressWrapper"></div>
        <div id="response">
            <h2>错误信息</h2>
        </div>
        <table id="fileTable">
            <thead>
                <tr>
                    <th>文件名</th>
                    <th>文件类型</th>
                    <th>文件编号</th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>
    </div>
    <script src="upload.js"></script>
</body>
</html>

CSS 文件 (styles.css)

body {
    font-family: Arial, sans-serif;
    margin: 20px;
}

#uploadContainer {
    margin-bottom: 20px;
}

label, button {
    display: block;
    margin-top: 10px;
}

#progressWrapper {
    width: 100%;
    background: #f3f3f3;
    border: 1px solid #ccc;
    height: 20px;
    position: relative;
    margin-top: 10px;
}

.progressBar {
    height: 100%;
    background: green;
    text-align: center;
    color: white;
    line-height: 20px;
}

#fileTable {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
}

#fileTable th, #fileTable td {
    border: 1px solid #ccc;
    padding: 10px;
    text-align: left;
}

#error {
    color: red;
}

JavaScript 文件 (upload.js)

document.addEventListener('DOMContentLoaded', () => {
    const fileInput = document.getElementById('fileInput');
    const uploadButton = document.getElementById('uploadButton');
    const progressWrapper = document.getElementById('progressWrapper');
    const responseDiv = document.getElementById('response');
    const fileTableBody = document.querySelector('#fileTable tbody');

    let selectedFiles = [];

    fileInput.addEventListener('change', (event) => {
        selectedFiles = Array.from(event.target.files);
        displayProgressBars();
    });

    uploadButton.addEventListener('click', () => {
        if (selectedFiles.length === 0) {
            alert('请先选择文件');
            return;
        }
        uploadFiles();
    });

    function displayProgressBars() {
        progressWrapper.innerHTML = '';
        selectedFiles.forEach((file, index) => {
            const progressBar = document.createElement('div');
            progressBar.className = 'progressBar';
            progressBar.id = `progress_${index}`;
            progressBar.style.width = '0%';
            progressBar.innerText = `${file.name} - 0%`;
            progressWrapper.appendChild(progressBar);
        });
    }

    async function uploadFiles() {
        for (let i = 0; i < selectedFiles.length; i++) {
            await uploadFile(selectedFiles[i], i);
        }
        sendJsonArray();
        selectedFiles = [];
        fileInput.value = '';
    }

    function uploadFile(file, index) {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            const formData = new FormData();
            formData.append('file', file);

            xhr.upload.addEventListener('progress', (event) => {
                if (event.lengthComputable) {
                    const percentComplete = (event.loaded / event.total) * 100;
                    const progressBar = document.getElementById(`progress_${index}`);
                    progressBar.style.width = `${percentComplete}%`;
                    progressBar.innerText = `${file.name} - ${Math.round(percentComplete)}%`;
                }
            });

            xhr.onreadystatechange = () => {
                if (xhr.readyState === XMLHttpRequest.DONE) {
                    if (xhr.status === 200) {
                        const response = JSON.parse(xhr.responseText);
                        console.log(response);
                        const fileType = file.name.endsWith('.jpg') ? 11 : 0;
                        const fileData = {
                            fileNo: response.data,
                            fileType: fileType
                        };
                        addFileToTable(file.name, fileType, response.data);
                        localStorage.setItem(`file_${index}`, JSON.stringify(fileData));
                        resolve();
                    } else {
                        responseDiv.innerText = `Error uploading ${file.name}: ${xhr.responseText}`;
                        reject();
                    }
                }
            };

            xhr.open('POST', 'http://192.168.0.188:8098/VR-Editor/resource/upload');
            xhr.setRequestHeader('ContentType', 'multipart/form-data');
            xhr.send(formData);
        });
    }

    function sendJsonArray() {
        const fileList = [];
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            if (key.startsWith('file_')) {
                fileList.push(JSON.parse(localStorage.getItem(key)));
            }
        }

        const xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://192.168.0.188:8098/VR-Editor/file-edit/file-edit', true);
        xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
        xhr.onreadystatechange = () => {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    console.log('JSON array sent successfully');
                    localStorage.clear();
                    clearTable();
                } else {
                    responseDiv.innerText = `Error sending JSON array: ${xhr.responseText}`;
                }
            }
        };
        xhr.send(JSON.stringify(fileList));
    }

    function addFileToTable(fileName, fileType, fileNo) {
        const row = document.createElement('tr');
        row.innerHTML = `<td>${fileName}</td><td>${fileType}</td><td>${fileNo}</td>`;
        fileTableBody.appendChild(row);
    }

    function clearTable() {
        fileTableBody.innerHTML = '';
    }
});

4. 总结

通过本文的示例代码,我们学习了如何使用 HTML、CSS 和 JavaScript 创建一个支持多文件上传的网页应用。我们实现了选择文件、显示上传进度、上传文件并展示上传结果等功能。最终,我们将上传成功的文件信息保存到本地存储,并在上传完成后发送到服务器。希望本文对您理解和实现文件上传功能有所帮助。

本文标签: 上传文件 并保存 上传 功能 服务器