这里我只会说说一些完成 file upload 的基础 API。
很多项目我们需要上传文件。
有简单的 input file, 有需要验证的,有需要压缩的(img),有需要分段的(video),有需要体验好(display on local, ajax & percent) 等等
要完成以上的所有需求,我们需要很多底层的 API, 比如 File, FileReader, Canvas , XMLHttpRequest , Blob
要把这个控件写好的话,需要一些设计模式,不过这篇不会涉及这个,我只是想大略的说说过程和使用到的API方法,如何去设计就交给你们自己了。
参考 :
http://javascript.ruanyifeng.com/bom/ajax.html
http://www.html5rocks.com/zh/tutorials/file/dndfiles/
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
http://www.w3schools.com/tags/canvas_drawimage.asp
https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice
http://www.codicode.com/art/upload_and_save_a_canvas_image_to_the_server.aspx
基本的步骤是这样的
1. input file addEventListener change 监听 input file (你要用 drag drop 替代也行)
2. 得到 file 对象之后你就可以检查 file.name,file.type,file.size 等等了
3. 我可以通过 FileReader.readAsDataURL(file); 来获取一个 base64 string (这个是针对图片的处理,如果是txt的话你可以用别的 FileReader.readAs...其它)
4. 把这个 base64 放入img.src = base64 的话就可以在本地显示图片了
5. 在打开一个canvas 后,我们可以把上面的这张相片放入 canvas , 修改它的尺寸,加水印等等.
6. canvas.toDataURL() 把图像转换回 base64 string.
7. 通过XMLHttpRequest 上传这个 base64 string. (XMLHttpRequest 可以监听 process percent)
8. 后端把 base64 convert to byte 写入 fileStream 就完成了。
如果要支持分段上传的话,base64应该直接substring记入index position 就可以了。
如果上传的是 file 不是 base64 的话,可以使用 Blob.webkitSlice() | Blob.slice
document.getElementById("file").addEventListener("change", function (e) {
var files = S.toArray(this.files);
var file = files[0];
var fileReader = new FileReader(); fileReader.onloadend = function (e) {
var img = new Image();
img.onload = function () {
//比例要是尺寸
var MAX_WIDTH = 2560 / 2;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var height = this.height * (MAX_WIDTH / this.width);
canvas.width = MAX_WIDTH;
canvas.height = height;
//画图
//参数就是把img 的x,y,widthLength,heightLength copy
//然后 paste to canvas 的 x,y,widthLength,heightLength
context.drawImage(this, 0, 0, this.width, this.height, 0, 0, MAX_WIDTH, height); var base64 = canvas.toDataURL("image/jpeg", 0.8); //default 会是 png 格式,第2参数是压缩质量 0-1 (png 不可以压缩)
base64 = base64.replace(/^data:image\/(png|jpeg);base64,/, ""); //后端保存的时候不可以有前面这些字,所以在这里先去除 var http = new XMLHttpRequest();
var formData = new FormData();
formData.append("file", base64);
http.open("POST", "//localhost:8054/module/Upload/UploadAjax.ashx", true);
http.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
var imgSrc = this.responseText;
}
else if (this.status == 0) { //abort 会"同步"执行这里 }
else {
log("file upload ajax fail, looping upload stoped. statusCode : " + this.status);
}
}
}
http.upload.onprogress = function (e) {
if (e.lengthComputable) {
var percent = parseFloat(e.loaded / e.total * 100).toFixed(0); //八仙
}
}
http.send(formData);
}
img.src = this.result;
}
fileReader.readAsDataURL(file); }, false);
//upload base64 的处理
string path = context.Server.MapPath(@"~\img\" + "abc.jpeg");
using (FileStream fs = new FileStream(path, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(context.Request.Form["file"]);
bw.Write(data);
bw.Close();
}
}
context.Response.ContentType = "text/plain";
context.Response.Write(path);
//update file 的处理
string[] fileKeys = context.Request.Files.AllKeys;
string fileName = "";
foreach (string fileKey in fileKeys)
{
HttpPostedFile file = context.Request.Files[fileKey];
string extension = "." + file.ContentType.Substring();
//string extension = file.FileName.Substring(file.FileName.LastIndexOf("."));
fileName = Guid.NewGuid() + extension;
file.SaveAs(context.Server.MapPath(@"~\img\" + fileName));
}
context.Response.ContentType = "text/plain";
context.Response.Write(fileName);
有一点要说明一下,canvas to base64 png 的话,size 是非常大的, 比源文件还要大的多,所以png 格式是不能通过canvas做压缩的. (如果我错了,请告诉我)
所以一般上我们是对jpeg做压缩, 质量设置成0.92 的话,size 会和源文件相同. 不过0.92并不是default的设置,default设置会再低一些。
上面我没有实现水印和分段,以后等我有时间写一个完整的控件时,我才更新。
上传文件 file upload 学习笔记的更多相关文章
-
DVWA 黑客攻防演练(五)文件上传漏洞 File Upload
说起文件上传漏洞 ,可谓是印象深刻.有次公司的网站突然访问不到了,同事去服务器看了一下.所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映 ...
-
vuetify | vue | 文件上传组件 | file | upload | form input[type=";file";]
今天无聊地写vuecli3听歌的时候,遇到了上传文件到Django的自我需求,然后就到vuetify的表单组件里找upload btn,发现居然没有!!! 顿时惊了个呆,要知道之前用element做操 ...
-
Ajax JQuery HTML 提交上传文件File HTML+ Ajax+ASP.NET+ WebService
起因:公司最近有些项目用到了HTML+WebService的组合,发现访问速度等都快了许多,但是由于通过Ajax只能应付一些简单的文字类的传输,上传文件就捉襟见肘了,如果一直引用第三方的swf之类上传 ...
-
php Socket模拟表单上传文件函数_学习
模拟上传文件的php代码 里面访问地址.主机.上传文件名.内容.分隔符可以修改 function postFile($file) { $clf = "\r\n"; ...
-
Spring MVC-表单(Form)标签-文件上传(File Upload)示例(转载实践)
以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_upload.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显 ...
-
JQuery上传文件插件Uploadify使用笔记
新工作的第一份任务就是给实现 限制Uploadify 上传文件格式为图片 测试出来报错,选择了非图片文件,提示错误后,再选择其他文件,上传时还是包含了之前清空的非图片文件 最后实现效果的代码是 //上 ...
-
使用vue+iview实现上传文件及常用的下载文件的方法
首先说明一下,我们这次主要用的还是iview的upload上传组件,下面直接上代码 <Upload ref="upload" multiple='true' //是否支持多文 ...
-
SpringMVC+jquery.uploadify 上传文件
前言 以前用Asp.net MVC+uploadify上传文件,最近学习SpringMVC,所以就用SpringMVC+uploadify做个上传文件的demo. 刚开始用form表单的方式提交,在C ...
-
JAVA模拟HTTP post请求上传文件
在开发中,我们使用的比较多的HTTP请求方式基本上就是GET.POST.其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等.而我们在使用HTTP请求时中遇到的比较 ...
随机推荐
-
iOS常用第三方库
1.AFNetworking 轻量级的通讯类库,使用非常简单. 下载地址:https://github.com/AFNetworking/AFNetworking 2.FMDB fmdb是一个数据 ...
-
浅析Java内存模型
概述 Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.此处的变量是线程共享的,存在竞争问题的. Java内存模型规定了所有的变量 ...
-
【转】Angular运行原理揭秘 Part 1
当你用AngularJS写的应用越多, 你会越发的觉得它相当神奇. 之前我用AngularJS实现了相当多酷炫的效果, 所以我决定去看看它的源码, 我想这样也许我能知道它的原理. 下面是我从源码中找到 ...
-
uboot之board.c源码分析
/lib_arm/board.c 主要完成了一些初始化的操作,最重要的是有start_armboot函数 _armboot_start地址为多少?? /* * * U-Boot code: 00F00 ...
-
走进C++程序世界------继承和派生
继承和派生 继承是面向对象编程语言的最重要方面之一,正确的使用继承可编写出设计良好,容易于维护和扩展的应用程序.下面是在其他博客中的总结: ****************************** ...
-
BZOJ 3170: [Tjoi 2013]松鼠聚会( sort )
题目的距离为max(|x1-x2|, |y1-y2|) (切比雪夫距离). 切比雪夫距离(x, y)->曼哈顿距离((x+y)/2, (x-y)/2) (曼哈顿(x, y)->切比雪夫(x ...
-
【Kafka】
KafkaProducer Kafka消息发布客户端. 线程安全,跨线程共享单个生产者实例通常比拥有多个实例的速度更快. 例子,使用生产者发送包含序列号的字符串作为键/值对的记录: Propertie ...
-
while循环写3次用户名密码验证程序
#变量来自原始用户名和密码 username = 'admin' password = 'nimda' #变量来自计数器 count = 0 #循环条件计数器小于3,则执行while代码块 while ...
-
jmeter之使用代理录制脚本
从loadrunner到jmeter,录制压力测试脚本好像都只支持IE,近来才知道jmeter还有自带的录制脚本元件, 且支持IE.Chrome及Firefox等多种浏览器.这里就记录一下通过jmet ...
-
python 全栈开发,Day110(django ModelForm,客户管理之 编辑权限(一))
昨日内容回顾 1. 简述权限管理的实现原理. 粒度控制到按钮级别的权限控制 - 用户登陆成功之后,将权限和菜单信息放入session - 每次请求时,在中间件中做权限校验 - inclusion_ta ...