这里我只会说说一些完成 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 学习笔记的更多相关文章

  1. DVWA 黑客攻防演练(五)文件上传漏洞 File Upload

    说起文件上传漏洞 ,可谓是印象深刻.有次公司的网站突然访问不到了,同事去服务器看了一下.所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映 ...

  2. vuetify | vue | 文件上传组件 | file | upload | form input[type="file"]

    今天无聊地写vuecli3听歌的时候,遇到了上传文件到Django的自我需求,然后就到vuetify的表单组件里找upload btn,发现居然没有!!! 顿时惊了个呆,要知道之前用element做操 ...

  3. Ajax JQuery HTML 提交上传文件File HTML+ Ajax+ASP.NET+ WebService

    起因:公司最近有些项目用到了HTML+WebService的组合,发现访问速度等都快了许多,但是由于通过Ajax只能应付一些简单的文字类的传输,上传文件就捉襟见肘了,如果一直引用第三方的swf之类上传 ...

  4. php Socket模拟表单上传文件函数_学习

    模拟上传文件的php代码 里面访问地址.主机.上传文件名.内容.分隔符可以修改   function postFile($file) {     $clf = "\r\n";   ...

  5. Spring MVC-表单(Form)标签-文件上传(File Upload)示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_upload.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显 ...

  6. JQuery上传文件插件Uploadify使用笔记

    新工作的第一份任务就是给实现 限制Uploadify 上传文件格式为图片 测试出来报错,选择了非图片文件,提示错误后,再选择其他文件,上传时还是包含了之前清空的非图片文件 最后实现效果的代码是 //上 ...

  7. 使用vue+iview实现上传文件及常用的下载文件的方法

    首先说明一下,我们这次主要用的还是iview的upload上传组件,下面直接上代码 <Upload ref="upload" multiple='true' //是否支持多文 ...

  8. SpringMVC+jquery.uploadify 上传文件

    前言 以前用Asp.net MVC+uploadify上传文件,最近学习SpringMVC,所以就用SpringMVC+uploadify做个上传文件的demo. 刚开始用form表单的方式提交,在C ...

  9. JAVA模拟HTTP post请求上传文件

    在开发中,我们使用的比较多的HTTP请求方式基本上就是GET.POST.其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等.而我们在使用HTTP请求时中遇到的比较 ...

随机推荐

  1. Windows 已在 DImageProcess.exe 中触发一个断点。

    其原因可能是堆被损坏,这说明 DImageProcess.exe 中或它所加载的任何 DLL 中有 Bug. 原因也可能是用户在 DImageProcess.exe 具有焦点时按下了 F12. 输出窗 ...

  2. CloudFoundry云环境中应用的特殊设计

    常规的应用,大多数可以不经过任何修改即可部署于CloudFoundry云平台之上,但是在一些特殊情况下,总是不可避免地会出现一些细小的问题,如果在应用设计之初,就考虑到针对云平台的一些特殊情况,遵守云 ...

  3. linux关闭防火墙及selinux

    RHEL6.5 查看linux防护墙状态: service iptables status 关闭linux防火墙: 1)永久关闭,重启后生效 开启: chkconfig iptables on 关闭: ...

  4. BaseAdapter的ArrayIndexOutOfBoundsException

    最近写一个listView中多个listItem布局时,convertView缓存及使用,类似微信的聊天界面的listView,报了一个异常: 11-25 15:51:49.076: E/InputE ...

  5. Html5新特性 &lt;canvas&gt;画板画直线

     以下样例为用canvas标签画多条直线 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" & ...

  6. SQL语句查询结果额外加入一列序号自己主动添加

    sqlserver 能够用row_number函数实现 例如以下: SELECT *,row_number() OVER(ORDER BY score(列名) DESC) AS rank FROM s ...

  7. Zend框架2入门(二) (转)

    Zend框架2使用一个模块系统,和你组织内每个你的主应用程序特定代码模块.骨架提供的应用程序模块是用于提供引导,错误和路由配置到整个应用程序.它通常是用来提供应用水平控制器,比如说,应用程序的主页,但 ...

  8. unity3d触屏操作对象运动

    using UnityEngine; using System.Collections; public class robot : MonoBehaviour { private GameObject ...

  9. java基本打印练习《我行我素购物系统》

    public class ShoppingSystem{ public static void main(String[] args){ //System.out.println("**** ...

  10. yii 自动生成的内容,分页信息(Displaying 1-10 of 15 results.)如何修改或是yii cgridview template summary

    问的白一点就是 Displaying 1-10 of 15 results 如何翻译 如果搜索的话, 搜这个会出来很多内容 yii cgridview template summary 好了,其他不说 ...