web开发之文件上传的多种实现方式「附代码」

1. 前言

文件上传功能是 Web 应用必不可少的一部分。本文将介绍几种在 Web 开发中实现文件上传的方式,并给出相应的代码示例。

2. 简单的文件上传

文件上传最基本的实现方式就是通过 HTML form 提交表单,并指定 enctype 属性为 multipart/form-data。后端应用程序需要能够处理接收到的文件数据,通常都是通过读取 HTTP 请求的 body 来获取文件数据。

以下是 HTML 表单代码:

<form action="upload.php" method="post" enctype="multipart/form-data">

<input type="file" name="file">

<input type="submit" value="Upload">

</form>

PHP 后端文件代码:

// 保存上传的文件

if ($_FILES['file']) {

$tempPath = $_FILES['file']['tmp_name'];

$destPath = 'uploads/' . $_FILES['file']['name'];

move_uploaded_file($tempPath, $destPath);

}

3. Dropzone.js 实现上传

3.1. Dropzone.js 简介

Dropzone.js 是一款基于 jQuery 的文件上传库,具有以下特点:

轻松实现拖拽文件上传

自动上传和手动上传两种方式

支持多文件上传

支持文件类型和大小限制

官方网站:https://www.dropzonejs.com/

3.2. 使用 Dropzone.js 实现上传

使用 Dropzone.js 实现文件上传需要导入 dropzone.css 和 dropzone.js 文件。

以下是 HTML 代码:

<form id="my-awesome-dropzone" class="dropzone" action="upload.php"></form>

JavaScript 代码:

// 初始化 Dropzone

Dropzone.options.myAwesomeDropzone = {

paramName: 'file', // 传递给后台的参数名

maxFilesize: 2, // 文件最大允许大小,单位为 MB

acceptedFiles: 'image/*', // 允许上传的文件类型

init: function() {

this.on('success', function(file, response) {

console.log('上传成功:' + response);

});

this.on('error', function(file, errorMessage) {

console.log('上传失败:' + errorMessage);

});

}

};

PHP 后端文件代码:

// 保存上传的文件

if ($_FILES['file']) {

$tempPath = $_FILES['file']['tmp_name'];

$destPath = 'uploads/' . $_FILES['file']['name'];

move_uploaded_file($tempPath, $destPath);

echo '文件上传成功!';

} else {

echo '文件上传失败!';

}

4. AJAX 实现文件上传

AJAX 是一种在不重新加载页面的情况下向服务器发送 HTTP 请求的技术。通过 AJAX 实现文件上传,可以在上传过程中显示上传进度,并且不需要刷新页面。

以下是 HTML 代码:

<form id="my-form">

<input type="file" id="file-input">

<button type="button" id="upload-btn">上传</button>

</form>

<progress id="progress-bar" max="100" value="0"></progress>

JavaScript 代码:

// 绑定上传按钮的点击事件

document.getElementById('upload-btn').addEventListener('click', function() {

var fileInput = document.getElementById('file-input');

var file = fileInput.files[0];

var formData = new FormData();

formData.append('file', file);

var xhr = new XMLHttpRequest();

xhr.upload.addEventListener('progress', function(evt) {

var percent = evt.loaded / evt.total * 100;

document.getElementById('progress-bar').value = percent;

}, false);

xhr.addEventListener('load', function(evt) {

console.log('上传完成!');

}, false);

xhr.addEventListener('error', function(evt) {

console.log('上传失败!');

}, false);

xhr.open('POST', 'upload.php');

xhr.send(formData);

});

PHP 后端文件代码与第 2 种方法相同,此处不再赘述。

5. WebSocket 实现文件上传

WebSocket 是一种全双工通信协议,通过 WebSocket 实现文件上传可以实时显示上传进度,并且可以在上传过程中暂停、继续上传。

以下是 HTML 代码:

<form id="my-form">

<input type="file" id="file-input">

<button type="button" id="upload-btn">上传</button>

</form>

<progress id="progress-bar" max="100" value="0"></progress>

JavaScript 代码:

// 创建 WebSocket 连接

var socket = new WebSocket('ws://127.0.0.1:8080');

// 绑定上传按钮的点击事件

document.getElementById('upload-btn').addEventListener('click', function() {

var fileInput = document.getElementById('file-input');

var file = fileInput.files[0];

// 发送文件信息

socket.send(JSON.stringify({

filename: file.name,

filesize: file.size

}));

// 分段上传文件数据

var chunkSize = 16 * 1024;

var offset = 0;

var reader = new FileReader();

reader.onload = function(evt) {

if (evt.target.readyState === FileReader.DONE) {

socket.send(evt.target.result);

offset += chunkSize;

document.getElementById('progress-bar').value = offset / file.size * 100;

if (offset < file.size) {

readSlice(offset);

}

}

};

function readSlice(start) {

var slice = file.slice(start, start + chunkSize);

reader.readAsArrayBuffer(slice);

}

readSlice(0);

});

// 显示上传进度

socket.addEventListener('message', function(evt) {

var data = JSON.parse(evt.data);

if (data.type === 'progress') {

document.getElementById('progress-bar').value = data.percent;

}

});

// 断开 WebSocket 连接

window.addEventListener('beforeunload', function() {

socket.close();

});

Node.js 服务端代码:

const WebSocket = require('ws');

const fs = require('fs');

const wss = new WebSocket.Server({ port: 8080 });

let currentSocket;

let currentSize = 0;

wss.on('connection', function connection(ws) {

currentSocket = ws;

console.log('Client connected');

});

wss.on('close', function close() {

console.log('Client disconnected');

});

wss.on('error', function error(err) {

console.log(err.message);

});

wss.on('message', function incoming(message) {

if (currentSocket) {

// 接收文件信息

const data = JSON.parse(message);

console.log(`File name: ${data.filename}, File size: ${data.filesize}`);

currentSize = 0;

// 创建一个可写流写入文件

const dest = fs.createWriteStream(`uploads/${data.filename}`);

currentSocket.on('message', function incoming(chunk) {

// 接收分段上传的文件数据

dest.write(chunk);

currentSize += chunk.length

currentSocket.send(JSON.stringify({

type: 'progress',

percent: currentSize / data.filesize * 100

}));

if (currentSize === data.filesize) {

dest.end();

console.log('File upload finished');

currentSocket = null;

}

});

} else {

console.log('No client connected');

}

});

6. 总结

Web 开发中实现文件上传的方式有多种,每种方式都有自己的优缺点和适用场景。在选择实现方式时,需要根据具体需求进行选择。