文件上传方式

文件上传的几种方式

1、表单上传

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表单上传</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="./uuid.js"></script>
</head>
<body>
	<h2>表单上传</h2>
    <form action="/api/upload" enctype="multipart/form-data" 		 		method="POST">
      <input name="file" type="file" id="file">
      <input type="submit" value="提交">
    </form>
    <script type="text/javascript">
    </script>
</body>
</html>

【备注】

知识点:
 enctype(encodetype):该属性规定在将表单数据发送到服务器之前如何对其进行编码。
		application/x-www-form-urlencoded: 在发送前编码所有字符(默认)
		multipart/form-data: 不对字符编码,在使用包含文件上传控件的表单时,必须使用该值。
		text/plain: 空格转换为 "+" 加号,但不对特殊字符编码。
     
重点:
  1、请求方式必须是 POST
	
  2、默认是对表单数据以 "application/x-www-form-urlencoded"进行编码。
	 	
  3、enctype(encodetype): 编码类型
     multipart/form-data: 已二进制形式上传文件,支持多种类型的文件上传
     application/x-www-form-urlencoded: 只能上传文本格式文件
		

缺点:
   1、表单提交属于同步提交,提交后整个页面都会发生跳转,用户体验很差。
   
   2、页面之前的状态和数据都会丢失。
   
解决办法:采用异步上传。

2、异步上传(formData)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>formData上传</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
    <h2>formData上传</h2>
    <input type="file" name="file" id="file">
    <button id="upload">上传</button>
    <script type="text/javascript">
        //发送请求
        $("#upload").click(upload)
        function upload() {
           var files = document.getElementById("file").files;
           var blob = document.getElementById("file").files[0];
           console.log("file: ", files);
            console.log("blob: ", blob);
            // 利用formData来传递数据
            var formData = new FormData();
            formData.append("文件名:", blob.name);
            formData.append("file", blob);
            
            // ajax 方法上传数据
            $.ajax({
            	url: "/api/upload",
            	type: "POST",
            	data: formData,
            	processData: false,  // 不处理数据
                contentType: false,  // 不设置内容类型
            }).done(function(res){
            	console.log('formData 方式上传表单成功!');
            }).fail(function(res){
            	console.log('formData 方式上传表单失败!');
            });
            
            // XMLHttpRequest 方法上传数据
            var request = new XMLHttpRequest();
            request.open("POST", "/api/upload");
            request.send(formData);
        }
    </script>
</body>
</html>

​ 【备注】

知识点:
	1、FormData 接口 是 XMLHttpRequest Level2 新加的接口。它提供了一种表单数据的键值对 key/value 的构		造方法,并且可以轻松的将数据通过 XMLHttpRequest.send() 方法发送出去。
	
	2、XMLHttpRequest(XHR) 对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定		的 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。
	
	3、file 是文件接口,它提供了有关文件的信息,并允许网页中 JS 访问其内容。
	
重点:
	1、formData 对象用以将数据编译成键值对,以便用 XMLHttpRequest 来发送数据。
	
	2、formData 对象附加的文件可以是 file 类型 和 Blob 类型。
	
	3、file 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。
	
	4、Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 	 ReadableStream(二进制流)来用于操作数据。
	
	5、在 formData 上传文件时,上传参数数据类型会影响请求头部 content-type 的值,所以不必设置 content-		type 的值,浏览器会根据文件类型自动配置。
	
拓展:
	目前,FromData 基本上满足我们的上传需求,但是当文件比较大时,普通的上传方式就会出现一些问题:
	
	1、文件上传超时。
	
	2、文件上传大小超限。
	
	3、上传耗时久。
	
	4、其它网络原因导致上传失败,且失败后需要从头开始。
	
解决办法:大文件上传。
	

3、大文件上传

通用解决方案:切片上传 + 秒传

切片上传:
	是指将一个大文件切割为若干个小文件,分为多个请求依次上传,后台再将文件碎片拼接为一个完整的文件,即使		某个碎片上传失败,也不会影响其它文件碎片,只需要重新上传失败的部分就可以了。优点是多个请求一起发送文件,	 提高了传输速度的上限。
	
秒传:
	是指将文件再传输之前计算其内容的散列值,也就是 Hash 值,将该值传到后台,如果后台存在 Hash 值一致的文	件,认为该文件上传完成。

​ 【文件切片】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>切片上传</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="./uuid.js"></script>
</head>
<body>
	<h2>切片上传</h2>
    <input type="file" name="file" id="file">
    <button id="upload">上传</button>
    <script type="text/javascript">
        //var bytesPerPiece = 1024 * 1024; // 每个文件切片大小定为1MB .
        var bytesPerPiece = 100 * 100;  // 测试数据
        var totalPieces;   //切片总数
        //发送请求
        $("#upload").click(upload)
        function upload() {
            
            var blob = document.getElementById("file").files[0];
            // 文件唯一标识符号,防止多个用户一起上传文件时切片混乱
            var uuidfolder = uuidv1();
           // var uuidfolder = 'wwwwwwwwww2222222222';
            // 开始切割的位置
            var start = 0;
            // 切割的结束位置
            var end;
            // 切片的索引
            var index = 0;
            // 回调计数器
            var count = 0;
            // 文件的大小
            var filesize = blob.size;
            // 文件的名称
            var filename = blob.name;
            //计算文件切片总数
            totalPieces = Math.ceil(filesize / bytesPerPiece);
            // 启动while循环对文件切片
            while(start < filesize) {
                // 设置切片的结束位置
                end = start + bytesPerPiece;
                // 对最后一片数据进行处理(可以省略)
                if(end > filesize) {
                    end = filesize;
                }
                // 切割文件
                var chunk = blob.slice(start,end);//切割文件
                // 给每一片切片设置名字,名字的值为原始名称加索引,这样做是为了让后端可以按照索引顺序合并图片。
                var sliceIndex= blob.name + index;
                // 利用formData来传递数据
                var formData = new FormData();
                formData.append("file", chunk, sliceIndex);
                formData.append("uuidfolder", uuidfolder);
                formData.append("imgorder", index);
                $.ajax({
                    url: '/api/upload',
                    type: 'POST',
                    data: formData,
                    processData: false,  // 不处理数据
                    contentType: false,  // 不设置内容类型
                }).done(function(res){ 
                    count++;
                    if(count==totalPieces){
                        console.log("上传结束,请求拼接接口,将切片信息拼接完整,返回图片url");
                        $.post('/merge',{id:uuidfolder},function(data){
                            console.log(data);
                        })
                    }
                }).fail(function(res) {
                    console.log("上传失败")
                });
                start = end;
                index++;
            }
        }
    </script>
</body>
</html>

​ 【文件合并】

// 接收切片信息接口
router.post('/upload3', upload.single('file'), function (req, res, next) {
  console.log(req.body)
  // 接受图片唯一标识符号
    let imgname = req.body.uuidfolder;
    // 接受切片索引
    let imgorder = req.body.imgorder;
    // 建立图片存储目录
    let imgpath = path.join(__dirname,'..','public/mult',imgname);
    // 判断目录是否存在,存在的话直接使用并存储切片,不存在的话就新建。
    if (fs.existsSync(imgpath)) {
      fs.readFile(req.file.path, function (err, data) {
        fs.writeFile(path.join(imgpath, imgorder), data, (err) => {
          if (!err) {
            res.send("写入后面的文件")
          }
        })
      })
    } else {
      fs.mkdirSync(imgpath);
      fs.readFile(req.file.path, function (err, data) {
        fs.writeFile(path.join(imgpath, imgorder), data, (err) => {
          if (!err) {
            res.send("第一次写入并新建文件夹")
          }
        })
      })
    }
})


// 合并图片接口:
router.post('/merge',function(req,res){
  let id = req.body.id;
  let folderpath = path.join(__dirname,"..",'public/mult',id);
  let destinpath = path.join(__dirname,"..",'public/img',id+'.jpg');
  let dist = '/img/'+id+'.jpg'
  fs.readdir(folderpath,function(err,arr){
    let arr2 = arr.map(e=>path.join(folderpath,e));
    concat(arr2, destinpath, function(err) {
      if (err) throw err
      res.send(dist);
    });
  })
})


// 注意:
	1、后端根据唯一标识符和切片下标来拼接文件。
	
	2、后端可以将接收和合并拆成两个接口来供前端调用,这样做的优点是节省服务端性能。
	
缺点:
	切片上传时并不能保证每个请求条件都成功,有可能因为各种原因导致部分切片丢失

4、大文件断点续传

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>断点续传</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="./uuid.js"></script>
</head>
<body>
	<h2>断点续传</h2>
    <input type="file" name="file" id="file">
    <button id="upload">上传</button>
    <script type="text/javascript">
        //var bytesPerPiece = 1024 * 1024; // 每个文件切片大小定为1MB .
        var bytesPerPiece = 300 * 300;  // 测试数据
        var totalPieces;   //切片总数
        //发送请求
        $("#upload").click(upload)
        function upload() {
            var blob = document.getElementById("file").files[0];
            // 文件唯一标识符号,防止多个用户一起上传文件时切片混乱
            //var uuidfolder = uuidv1();
            var uuidfolder = 'wwwwwwwwww2222222222';
            // 开始切割的位置
            var start = 0;
            // 切割的结束位置
            var end;
            // 切片的索引
            var index = 0;
            // 回调计数器
            var count = 0;
            // 文件的大小
            var filesize = blob.size;
            // 文件的名称
            var filename = blob.name;
            //计算文件切片总数
            totalPieces = Math.ceil(filesize / bytesPerPiece);
            // 判断是否为断点续传
            var continueNum = window.localStorage.getItem(uuidfolder)
            if(continueNum){
               index = continueNum 
	           start = index * bytesPerPiece
            } 
            // 启动while循环对文件切片
            while(start < filesize) {
                // 设置切片的结束位置
                end = start + bytesPerPiece;
                // 对最后一片数据进行处理(可以省略)
                if(end > filesize) {
                    end = filesize;
                }
                // 切割文件
                var chunk = blob.slice(start,end);//切割文件
                // 给每一片切片设置名字,名字的值为原始名称加索引,这样做是为了让后端可以按照索引顺序合并图片。
                var sliceIndex= blob.name + index;
                // 利用formData来传递数据
                var formData = new FormData();
                formData.append("file", chunk, sliceIndex);
                formData.append("uuidfolder", uuidfolder);
                formData.append("imgorder", index);
                
                // 人为制造断点
                if(index === 2){
                   console.log("断点续传")
                   window.localStorage.setItem(uuidfolder, index);
                   return;
                }
                
                $.ajax({
                    url: '/api/upload',
                    type: 'POST',
                    data: formData,
                    processData: false,  // 不处理数据
                    contentType: false,  // 不设置内容类型
                }).done(function(res){ 
                    count++;
                    if(count==totalPieces){
                        console.log("上传结束,请求拼接接口,将切片信息拼接完整,返回图片url");
                        $.post('/merge',{id:uuidfolder},function(data){
                            console.log(data);
                        })
                    }
                }).fail(function(res) {
                    console.log("上传失败")
                });
                start = end;
                index++;
            }
        }
    </script>
</body>
</html>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
u-upload 添加微信文件上传方式是指,在u-upload文件上传库中增加了支持微信文件上传的功能。通常情况下,u-upload库用于实现网站或应用中的文件上传功能,但原本的u-upload库并不支持微信文件上传。 微信文件上传是指用户通过微信平台将文件上传到网站或应用的过程。为了实现这一功能,开发人员对u-upload库进行了修改和调整,使其能够与微信平台进行交互。 具体而言,为了实现u-upload的微信文件上传方式,开发人员首先需要在网站或应用上放置一个微信登录的入口,以便用户可以使用微信登录,并授权访问其文件。 一旦用户使用微信登录并授权,u-upload库会调用微信接口获取用户在微信中上传的文件,并将其上传到指定的服务器上。开发人员需要在服务器端进行文件接收和处理的逻辑实现。 这样,用户就可以通过微信平台将文件上传到网站或应用中,实现了u-upload的微信文件上传方式。 需要注意的是,开发人员在实现u-upload的微信文件上传方式时,需要遵循微信平台的开发规范和技术要求,确保用户的文件上传过程安全可靠。此外,还需要处理文件上传过程中可能出现的错误和异常,确保系统的稳定性和可用性。 总之,通过对u-upload库的修改和调整,开发人员成功实现了u-upload的微信文件上传方式,使用户能够通过微信平台方便地将文件上传到网站或应用中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值