Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web中的文件上传和下载 #2

Open
54leibo opened this issue Jul 1, 2019 · 1 comment
Open

web中的文件上传和下载 #2

54leibo opened this issue Jul 1, 2019 · 1 comment

Comments

@54leibo
Copy link
Owner

54leibo commented Jul 1, 2019

文件上传

  • 传统形式上传(form 表单)
    • 表现:上传成功后跳转到 action属性 指定的地址
<form id="upload-form" action="upload.php" method="post" enctype="multipart/form-data" >
    <input type="file" id="upload" name="upload" /> <br />
    <input type="submit" value="Upload" />
</form>
  • iframe + form 表单:成功上传后可以避免页面刷新
html:
<form id="upload-form" action="upload.php" method="post" enctype="multipart/form-data" >
    <input type="file" id="upload" name="upload" /> <br />
    <input type="submit" value="Upload" />
</form>

js:
var form = $("#upload-form");

form.on('submit',function() {
  var seed = Math.floor(Math.random() * 1000);
  var id = "uploader-frame-" + seed;
  var callback = "uploader-cb-" + seed;
  var iframe = $('<iframe id="'+id+'" name="'+id+'" style="display:none;">');
  var url = form.attr('action');
  /*
  首先,它为表单添加target属性,指向动态插入的iframe窗口,这使得上传结束后,服务器将结果返回iframe窗口,所以当前页面就不会跳转了。其次,它在action属性指定的上传网址的后面,添加了一个参数,使得服务器知道回调函数的名称。这样就能将服务器返回的信息,从iframe窗口传到上层页面。
  */
  form.attr('target', id).append(iframe).attr('action', url + '?iframe=' + callback);
});


window[callback] = function(data){
    console.log('received callback:', data);
    iframe.remove(); //removing iframe
    form.removeAttr('target');
    form.attr('action', url);
    window[callback] = undefined; //removing callback
};

php(upload.php):
<script type="text/javascript">
    window.top.window['callback'](data);
</script>
  • ajax上传(借助 FormData对象)
if (window.FormData) {
  var formData = new FormData()
  // 建立一个upload表单项,值为上传的文件
  formData.append('upload', document.getElementById('upload').files[0])
  var xhr = new XMLHttpRequest()
  xhr.open('POST', $(this).attr('action'))
  // 定义上传完成后的回调函数
  xhr.onload = function () {
    if (xhr.status === 200) {
      console.log('上传成功')
    } else {
      console.log('出错了')
    }
  }
  xhr.send(formData)
}
  • ajax + 拖放上传
css:
#holder {
    border: 10px dashed #ccc;
    width: 300px;
    min-height: 300px;
    margin: 20px auto;
}
#holder.hover {
    border: 10px dashed #0c0;
}

html:
<div id="holder"></div>

js:
// 检查浏览器是否支持拖放上传。
if ('draggable' in document.createElement('span')) {
  var holder = document.getElementById('holder')
  holder.ondragover = function () {
    this.className = 'hover'
    return false
  }
  holder.ondragend = function () {
    this.className = ''
    return false
  }
  holder.ondrop = function (event) {
    event.preventDefault()
    this.className = ''
    var files = event.dataTransfer.files
    // do something with files
  }
}

文件下载

  • 设置 Http Header:Content-Disposition 消息头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。
  • Using a form element (Other than GET methods): form 元素,除了get方法
function downloadFile(actoinURL,filePath,fileName){
	var form = $("<form>");   
	$('body').append(form);
        form.attr('style','display:none');
        form.attr('target','');
        form.attr('method','post');
        form.attr('action',actoinURL);//下载文件的请求路径
        
        var input1 = $('<input>'); 
        input1.attr('type','hidden'); 
        input1.attr('name','filePath'); 
        input1.attr('value',filePath);
        form.append(input1);  
        var input2 = $('<input>'); 
        input2.attr('type','hidden'); 
        input2.attr('name','fileName'); 
        input2.attr('value',fileName);
        form.append(input2);
        
        form.submit();
  • a[download]: 带有 download 属性的a标签
    • 带有该属性的话浏览器将会下载它而不是跳转;如果download带有一个值它将作为默认文件名;对于文件名没有特别的要求/、\这两个符号会被转为下划线,同时每个系统会对文件命名有要求,浏览器会根据系统调整非法命名
    • 和 blob:URLs、data:URLs 一起使用,下载有 JavaScript 产生的数据,例如图片编辑软件产生的图片
    • 如果 HTTP header Content-Disposition 给了一个不同的 fileName, 优先使用 HTTP header Content-Disposition 指定的文件名
    • Content-Disposition 设置为了inline。谷歌浏览器依然会下载该文件,firefox则会采用 Content-Disposition 指定的方式处理(浏览器能展示则直接展示,无法展示则下载)
html:
<a id="download" href="">download</a>

js:
function downloadFile(fileName, content){
  var aLink = document.createElement('a');
  var blob = new Blob([content]);

  aLink.download = fileName;
  aLink.href = URL.createObjectURL(blob);
  aLink.click();
}
downloadFile('aa.txt', '123')
  • ajax 和 库FileSaver.js (原理同a[download])
    • 可以使用a标签的download来实现的
    • 特殊浏览器支持FileReader的,使用其构建URL,使用window.open或location.href来实现
    • 除了特殊的浏览器,使用URL.createObjectURL来构建对象URL,使用window.open或location.href来
  • ajax 和 库StreamSaver.js(利用 Service Workers 的 FetchEvent.respondWith(),构建一个 Content-Disposition返回)
  • 参考
@ranwawa
Copy link

ranwawa commented Nov 18, 2020

up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants