上传文件 file upload 学习笔记

这里我只会说说一些完成 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(6);
    //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设置会再低一些。

上面我没有实现水印和分段,以后等我有时间写一个完整的控件时,我才更新。

时间: 2024-10-12 08:43:32

上传文件 file upload 学习笔记的相关文章

DVWA 黑客攻防实战(五)文件上传漏洞 File Upload

说起文件上传漏洞 ,可谓是印象深刻.有次公司的网站突然访问不到了,同事去服务器看了一下.所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映射不到 jsp 文件,同事怀疑是攻击者上传了个 webshell 文件然后进行批量重命名了. 把后台的代码都找了一遍,后台代码也都有验证文件扩展名的,后面是发现一张普通的照片其实是代码来的,但也不知道为何能够执行.但看完这篇文章你就会明白了. 下面用 dvwa 来演示如何攻击和防御. 低级 用户界面

Android WebView 支持 文件上传(Html File Upload)

背景:有个html页面,用html里面自带的<input type =file/>上传文件(图片,word,Excel等)浏览器直接打开可以上传,套壳在Android app里面,点击文件上传没反应,修改Android代码,可以实现相应功能,亲测有效. 1.在oncreate 方法上面 加入以下代码: 1 private static final int REQUEST_STORAGE = 1; 2 private static final int REQUEST_LOCATION = 2;

上传文件——file标签深藏功与名

在Html标签中,<input type="file"/>是被用来上传文件的,但是这哥们儿在不同的浏览器下各有一副嘴脸,怎一个“别扭”了得.一直想解决这个头疼的问题,最近在读了一篇博文之后,忽然有了思路. 在上传文件时,<input type="file"/>是被放在一个form中,form既然要上传文件,一定是以post方式传输数据,enctype也要设置成multipart/form-data.如下: <form id="

postman测试请求API:方式post、上传文件file

这里介绍下postman测试请求API (1)测试get请求 根据请求文档API测试get请求,传参通过params传参 (2)测试post请求 通过body传参,但参数类型不同,分为文本类型和文件类型 其他为文件类型 1.文件类型 2.文本类型 . 原文地址:https://www.cnblogs.com/jianxian/p/12616854.html

SpringMVC+jquery.uploadify 上传文件

前言 以前用Asp.net MVC+uploadify上传文件,最近学习SpringMVC,所以就用SpringMVC+uploadify做个上传文件的demo. 刚开始用form表单的方式提交,在Controller Action中用@RequestParam MultipartFile file就能拿到上传文件信息.后我直接使用uploadify的方式上传,接口没有做任何调整,上传的过程中报http400, 客户端的请求不符合接口的要求,表单post提交时报文参数是以Form Data方式,

【转】JSP使用上传文件,并生产高清缩略图示例

原文地址:http://blog.csdn.net/yakson/article/details/9875731 前言 刚开始本来只想来测试一下Thumbnails生成缩略图的效果的,顺便来学一下jsp文件,开始没有使用commons-fileupload上 传组件,自己用纯jsp代码来编写,过程相当曲折.所以就不建议大家去编写纯JSP的上传代码了,想写的可以参考下commons-fileupload 的源码,里面很详细. 一.JSP上传文件 大家都知道,上传文件是以二进制上传的,这样可以让文件

JAVA模拟HTTP post请求上传文件

在开发中,我们使用的比较多的HTTP请求方式基本上就是GET.POST.其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等.而我们在使用HTTP请求时中遇到的比较麻烦的事情就是构造文件上传的HTTP报文格式,这个格式虽说也比较简单,但也比较容易出错.今天我们就一起来学习HTTP POST的报文格式以及通过Java来模拟文件上传的请求. 首先我们来看一个POST的报文请求,然后我们再来详细的分析它. POST报文格式 [plain] view plain co

JSP简单练习-上传文件

注意:在编写上传文件的代码时,需确保"WEB-INF/lib"下含有jspsmartupload.jar包,否则会出错. jspSmartupload.jar下载 <!-- uploadfileform.jsp --> <%@ page language="java" contentType="text/html; charset=gb2312" %> <html> <head> <title

form表单上传文件使用multipart请求处理

在开发Web应用程序时比较常见的功能之一,就是允许用户利用multipart请求将本地文件上传到服务器,而这正是Grails的坚固基石——spring MVC其中的一个优势.Spring通过对Servlet API的HttpServletRequest接口进行扩展,使其能够很好地处理文件上传.扩展后的接口名为org.springframework.web.multipart.MultipartHttpServletRequest,其内容如清单7-31所示. 清单7-31  org.springf