JavaScript:上传文件

标签 javascript file-upload

假设我在页面上有这个元素:

<input id="image-file" type="file" />

这将创建一个按钮,允许网页用户通过浏览器中的操作系统“文件打开...”对话框选择文件。

假设用户单击所述按钮,在对话框中选择一个文件,然后单击“确定”按钮关闭对话框。

所选文件名现在存储在:

document.getElementById("image-file").value

现在,假设服务器在 URL“/upload/image”处处理多部分 POST。

如何将文件发送到“/upload/image”?

另外,我如何收听文件上传完成的通知?

最佳答案

纯 JS

您可以使用 fetch可选用 await-try-catch

let photo = document.getElementById("image-file").files[0];
let formData = new FormData();
     
formData.append("photo", photo);
fetch('/upload/image', {method: "POST", body: formData});

async function SavePhoto(inp) 
{
    let user = { name:'john', age:34 };
    let formData = new FormData();
    let photo = inp.files[0];      
         
    formData.append("photo", photo);
    formData.append("user", JSON.stringify(user)); 
    
    const ctrl = new AbortController()    // timeout
    setTimeout(() => ctrl.abort(), 5000);
    
    try {
       let r = await fetch('/upload/image', 
         {method: "POST", body: formData, signal: ctrl.signal}); 
       console.log('HTTP response code:',r.status); 
    } catch(e) {
       console.log('Huston we have problem...:', e);
    }
    
}
<input id="image-file" type="file" onchange="SavePhoto(this)" >
<br><br>
Before selecting the file open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>

<br><br>
(in stack overflow snippets there is problem with error handling, however in <a href="https://jsfiddle.net/Lamik/b8ed5x3y/5/">jsfiddle version</a> for 404 errors 4xx/5xx are <a href="https://stackoverflow.com/a/33355142/860099">not throwing</a> at all but we can read response status which contains code)

老派方法 - xhr

let photo = document.getElementById("image-file").files[0];  // file from input
let req = new XMLHttpRequest();
let formData = new FormData();

formData.append("photo", photo);                                
req.open("POST", '/upload/image');
req.send(formData);

function SavePhoto(e) 
{
    let user = { name:'john', age:34 };
    let xhr = new XMLHttpRequest();
    let formData = new FormData();
    let photo = e.files[0];      
    
    formData.append("user", JSON.stringify(user));   
    formData.append("photo", photo);
    
    xhr.onreadystatechange = state => { console.log(xhr.status); } // err handling
    xhr.timeout = 5000;
    xhr.open("POST", '/upload/image'); 
    xhr.send(formData);
}
<input id="image-file" type="file" onchange="SavePhoto(this)" >
<br><br>
Choose file and open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>

<br><br>
(the stack overflow snippets, has some problem with error handling - the xhr.status is zero (instead of 404) which is similar to situation when we run script from file on <a href="https://stackoverflow.com/a/10173639/860099">local disc</a> - so I provide also js fiddle version which shows proper http error code <a href="https://jsfiddle.net/Lamik/k6jtq3uh/2/">here</a>)

摘要

  • 在服务器端,您可以读取 filename 中浏览器自动包含的原始文件名(和其他信息)。 formData 参数。
  • 您不需要设置请求头Content-Typemultipart/form-data - 这将由浏览器自动设置(包括 the mandatory boundary parameter)。
  • 而不是 /upload/image您可以使用完整地址,例如 http://.../upload/image (当然,这两个地址都是任意的,取决于服务器 - 与参数 method 的情况相同 - 通常在服务器上“POST”用于文件上传,但有时可以使用“PUT”或其他)。
  • 如果您想在单个请求中发送多个文件,请使用 multiple属性:<input multiple type=... /> ,并以类似的方式将所有选定的文件附加到 formData(例如 photo2=...files[2]; ... formData.append("photo2", photo2); )
  • 您可以包含额外的数据 (json) 来请求,例如let user = {name:'john', age:34}这样:formData.append("user", JSON.stringify(user));
  • 您可以设置超时时间:fetch使用 AbortController , 对于 xhr.timeout= milisec 的旧方法
  • 此解决方案应适用于所有主流浏览器。

关于JavaScript:上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5587973/

相关文章:

javascript - 带有 '&' 的参数打破了 $.ajax 请求

python - Django 文件上传内容类型为 "application/octet-stream"

javascript - 选择不上传所选文件的本地文件

python - 将任意文本文件的内容放入数据库的可靠方法(使用 Django/Python)?

c# - 如何更改浏览器的后退按钮功能,类似于 asp.net 中的电子商务网站

javascript - 选择指针下方的文本

javascript - 想要在区域悬停时更改图像源

javascript:向表格添加编号行

javascript - 从具有输入文件元素的表单访问文件

perl - 如何使用Catalyst上传文件?