JavaScript:上传文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5587973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:56:49  来源:igfitidea点击:

JavaScript: Upload file

javascriptfile-upload

提问by YummyBánhMì

Let's say I have this element on the page:

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

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

This will create a button that allows the users of the web page to select a file via an OS "File open..." dialog in the browser.

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

Let's say the user clicks said button, selects a file in the dialog, then clicks the "Ok" button to close the dialog.

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

The selected file name is now stored in:

所选文件名现在存储在:

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

Now, let's say that the server handles multi-part POSTs at the URL "/upload/image".

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

How do I send the file to "/upload/image"?

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

Also, how do I listen for notification that the file is finished uploading?

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

回答by Matt Ball

Unless you're trying to upload the file using ajax, just submit the formto /upload/image.

除非您尝试使用 ajax 上传文件,否则只需将表单提交/upload/image.

<form enctype="multipart/form-data" action="/upload/image" method="post">
    <input id="image-file" type="file" />
</form>

If you do want to upload the image in the background (e.g. without submitting the whole form), you can use ajax:

如果您确实想在后台上传图片(例如不提交整个表单),您可以使用 ajax:

回答by Kamil Kie?czewski

Pure JS

纯JS

You can use fetchoptionally with await-try-catch

您可以选择将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));  
    
    try {
       let r = await fetch('/upload/image', {method: "POST", body: formData}); 
       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)

Old school approach - xhr

老派方法 - 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.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>)

SUMMARY

概括

  • In server side you can read original file name (and other info) which is automatically included to request by browser in filenameformData parameter.
  • You do NOT need to set request header Content-Typeto multipart/form-data- this will be set automatically by browser.
  • Instead of /upload/imageyou can use full address like http://.../upload/image.
  • If you want to send many files in single request use multipleattribute: <input multiple type=... />, and attach all chosen files to formData in similar way (e.g. photo2=...files[2];... formData.append("photo2", photo2);)
  • You can include additional data (json) to request e.g. let user = {name:'john', age:34}in this way: formData.append("user", JSON.stringify(user));
  • This solutions should work on all major browsers.
  • 在服务器端,您可以读取原始文件名(和其他信息),该文件名自动包含在浏览器的filenameformData 参数中请求。
  • 您不需要将请求标头设置Content-Typemultipart/form-data- 这将由浏览器自动设置。
  • 而不是/upload/image您可以使用完整地址,如http://.../upload/image.
  • 如果您想在单个请求中发送多个文件,请使用multipleattribute: <input multiple type=... />,并以类似方式将所有选定的文件附加到 formData(例如photo2=...files[2];... formData.append("photo2", photo2);
  • 您可以包含其他数据(json)以请求例如let user = {name:'john', age:34}以这种方式:formData.append("user", JSON.stringify(user));
  • 此解决方案应适用于所有主要浏览器。