为了避免在实现简单的异步文件上传功能时候引入一个第三方库文件的尴尬情形(库文件可能造成多余的开销,拉低应用加载速度,尤其是在引入库文件之后仅使用其中一两个功能的情况下,性价比极低),最近了解了一下文件异步上传的实现原理,顺带看了看进度条、图片预览等功能的实现,做一点简单的整理。
文件上传
HTML结构如下,一个file input和一个button。当点击“上传”按钮的时候,将file input选中的文件上传到服务器。
<input type="file" name="file" id="file" /> <button id="upload">上传</button>
以下是“上传”按钮的点击事件处理器,点击按钮之后通过一个XMLHttpRequest对象来实现发送异步请求。上传的内容为文件,因此还需要用到FormData对象,FormData可以js里面创建表单对象,将file input的文件append到FormData对象中,最后调用XHR对象的send()方法将表单数据发送出去即可。
var file = document.querySelector('#file'); var upload = document.querySelector('#upload'); var xhr = new XMLHttpRequest(); // 点击上传 function uploadFile(event) { var formData = new FormData(); formData.append('test-upload', file.files[0]); xhr.onload = uploadSuccess; xhr.open('post', '/upload', true); xhr.send(formData); } // 成功上传 function uploadSuccess(event) { if (xhr.readyState === 4) { console.log(xhr.responseText); } }
上传进度
在进行文件上传的时候,xhr对象会有一个upload属性,会提供一个progress事件,在相应的事件处理器里面通过事件对象可以知道当前的上传进度,利用这个特点可以很方便地实现进度条或者进度提示。
<input type="file" name="file" id="file" /> <button id="upload">上传</button> <span id="progress">0%</span>
var progress = document.querySelector('#progress'); // 点击上传 function uploadFile(event) { var formData = new FormData(); formData.append('test-upload', file.files[0]); xhr.onload = uploadSuccess; xhr.upload.onprogress = setProgress; xhr.open('post', '/upload', true); xhr.send(formData); } // 进度条 function setProgress(event) { if (event.lengthComputable) { var complete = Number.parseInt(event.loaded / event.total * 100); progress.innerHTML = complete + '%'; } }
图片预览
上传图片的时候可以利用FileReader对象来实现图片预览。FileReader可以异步读取用户电脑上的文件,将file input选中的文件传给FileReader,读取之后取得文件的URL并设置为image元素的src即可让选中的图片文件显示出来。
<input type="file" name="file" id="file" /> <button id="upload">上传</button> <span id="progress">0</span> <img id="image" src="" width="200" />
var file = document.querySelector('#file'); file.addEventListener('change', previewImage, false); // 图片预览 function previewImage(event) { var reader = new FileReader(); reader.onload = function (event) { image.src = event.target.result; }; reader.readAsDataURL(event.target.files[0]); }
服务端处理
使用express搭建一个简单的NodeJS服务端,提供上传文件的接口。express要支持文件上传需要用到中间件,在express官网上有很多介绍。这里我使用的是multer中间件,下面是简单的使用示例。upload.single表示这个接口接受的上传文件数量为1个,'test-upload'限制了上传的表单数据的键为'test-upload'(formData.append(‘test-upload', file.files[0]);)。经过这个中间件处理之后,通过req.file可以访问到文件的相关信息,上传的文件存放在uploads文件夹中。
const upload = require('multer')({ dest: 'uploads/' }); app.post('/upload', upload.single('test-upload'), (req, res) => { // 没有附带文件 if (!req.file) { res.json({ ok: false }); return; } // 输出文件信息 console.log('===================================================='); console.log('fieldname: ' + req.file.fieldname); console.log('originalname: ' + req.file.originalname); console.log('encoding: ' + req.file.encoding); console.log('mimetype: ' + req.file.mimetype); console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB'); console.log('destination: ' + req.file.destination); console.log('filename: ' + req.file.filename); console.log('path: ' + req.file.path); });
由输出可以看到,文件的命名使用一个哈希值表示,并且去除了后缀名,想要保持文件的原有的命名格式,需要再通过fs对文件进行改名。
app.post('/upload', upload.single('test-upload'), (req, res) => { // 没有附带文件 if (!req.file) { res.json({ ok: false }); return; } // 输出文件信息 console.log('===================================================='); console.log('fieldname: ' + req.file.fieldname); console.log('originalname: ' + req.file.originalname); console.log('encoding: ' + req.file.encoding); console.log('mimetype: ' + req.file.mimetype); console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB'); console.log('destination: ' + req.file.destination); console.log('filename: ' + req.file.filename); console.log('path: ' + req.file.path); // 重命名文件 let oldPath = path.join(__dirname, req.file.path); let newPath = path.join(__dirname, 'uploads/' + req.file.originalname); fs.rename(oldPath, newPath, (err) => { if (err) { res.json({ ok: false }); console.log(err); } else { res.json({ ok: true }); } }); });
完整代码
ajax异步文件上传、进度显示、图片预览
<input type="file" name="file" id="file" /> <button id="upload">上传</button> <span id="progress">0</span> <img id="image" src="" width="200" />
(function () { 'use strict'; var file = document.querySelector('#file'); var upload = document.querySelector('#upload'); var progress = document.querySelector('#progress'); var image = document.querySelector('#image'); var xhr = new XMLHttpRequest(); upload.addEventListener('click', uploadFile, false); file.addEventListener('change', previewImage, false); // 点击上传 function uploadFile(event) { var formData = new FormData(); formData.append('test-upload', file.files[0]); xhr.onload = uploadSuccess; xhr.upload.onprogress = setProgress; xhr.open('post', '/upload', true); xhr.send(formData); } // 成功上传 function uploadSuccess(event) { if (xhr.readyState === 4) { console.log(xhr.responseText); } } // 进度条 function setProgress(event) { if (event.lengthComputable) { var complete = Number.parseInt(event.loaded / event.total * 100); progress.innerHTML = complete + '%'; } } // 图片预览 function previewImage(event) { var reader = new FileReader(); reader.onload = function (event) { image.src = event.target.result; }; reader.readAsDataURL(event.target.files[0]); } })();
express服务器提供文件上传接口
const express = require('express'); const upload = require('multer')({ dest: 'uploads/' }); const path = require('path'); const fs = require('fs'); const port = 8080; let app = express(); app.set('port', port); // index.html, index.js放在static文件夹中 app.use(express.static(path.join(__dirname, 'static'))); app.get('*', (req, res) => { res.redirect('index.html'); }); app.post('/upload', upload.single('test-upload'), (req, res) => { // 没有附带文件 if (!req.file) { res.json({ ok: false }); return; } // 输出文件信息 console.log('===================================================='); console.log('fieldname: ' + req.file.fieldname); console.log('originalname: ' + req.file.originalname); console.log('encoding: ' + req.file.encoding); console.log('mimetype: ' + req.file.mimetype); console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB'); console.log('destination: ' + req.file.destination); console.log('filename: ' + req.file.filename); console.log('path: ' + req.file.path); // 重命名文件 let oldPath = path.join(__dirname, req.file.path); let newPath = path.join(__dirname, 'uploads/' + req.file.originalname); fs.rename(oldPath, newPath, (err) => { if (err) { res.json({ ok: false }); console.log(err); } else { res.json({ ok: true }); } }); }); app.listen(port, () => { console.log("[Server] localhost:" + port); });
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持小牛知识库!
异步文件读写 读文件 use AsyncFile; $content = (yield AsyncFile::read(__ROOT__."runtime/test.txt")); 写文件 $res = (yield AsyncFile::write(__ROOT__."runtime/test.txt", "hello wordls!")); $res = (yi
问题内容: 以下是我用于将文件上传到服务器的代码。但是,即使经过几次尝试,甚至添加了严格模式,我都遇到了网络异常。 我是Android的新手,不知道如何使用异步任务,许多人建议您使用这种异步网络操作。谁能告诉我代码中哪里有错误以及应该在哪里使用异步任务? 问题答案: 有关更多信息,请参考此链接 http://vikaskanani.wordpress.com/2011/01/29/android-
本文向大家介绍Ajax异步上传文件实例代码分享,包括了Ajax异步上传文件实例代码分享的使用技巧和注意事项,需要的朋友参考一下 非常不多说,直接给大家上干货,写的不好还请见谅。 具体代码如下所示: 以上代码是小编给大家分享的Ajax异步上传文件实例代码,希望对大家有所帮助,如果大家有疑问欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对呐喊教程网站的支持!
本文向大家介绍jquery中的ajax异步上传,包括了jquery中的ajax异步上传的使用技巧和注意事项,需要的朋友参考一下 找了好久终于在网上找到了ajax异步上传文件的方法,不过网上大多数是php的 ,我改为struts2写的 大同小异,希望对学习java的人有一定的帮助。我上传的是音乐文件。 ajaxfileupload.js这个js文件是主要文件,一定要导入。 jsp页面 ,其中我还做
本文向大家介绍ajax实现异步文件或图片上传功能,包括了ajax实现异步文件或图片上传功能的使用技巧和注意事项,需要的朋友参考一下 大家好,这篇文章我要给大家分享一个网页文件上传功能的代码,希望大家可以有所参考,或者给我提些建议。 众所周知现在的各大网站基本都设有文件上传功能,用户可以把自己喜欢的图片或其他文件放在网上存起来,以便以后用的时候方便去找,可是一个网页的文件上传功能究竟该怎么去设置呢?
本文向大家介绍PHP+Ajax异步带进度条上传文件实例,包括了PHP+Ajax异步带进度条上传文件实例的使用技巧和注意事项,需要的朋友参考一下 最近项目中要做一个带进度条的上传文件的功能,学习了Ajax,使用起来比较方便,将几个方法实现就行。 前端引入文件 Ajax进度条异步处理 前端上传HTML PHP文件上传类 文件上传效果如图: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多