假设页面上有这个元素:

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

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

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

所选的文件名现在存储在:

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

现在,让我们假设服务器在URL“/upload/image”处处理多个部分的post。

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

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


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

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

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

异步文件上传(AJAX文件上传)使用jsp和javascript jQuery Ajax文件上传 使用文件上传的Ajax


纯JS

你可以选择使用fetch和wait-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>)

总结

In server side you can read original file name (and other info) which is automatically included to request by browser in filename formData parameter. You do NOT need to set request header Content-Type to multipart/form-data - this will be set automatically by browser (which will include the mandatory boundary parameter). Instead of /upload/image you can use full address like http://.../upload/image (of course both addresses are arbitrary and depends on server - and same situation with param method - usually on servers "POST" is used for file upload but sometimes "PUT" or other can be used). If you want to send many files in single request use multiple attribute: <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)); You can set timeout: for fetch using AbortController, for old approach by xhr.timeout= milisec This solutions should work on all major browsers.


我已经试着这么做了一段时间,但这些答案都对我不起作用。我是这么做的。

我有一个选择文件和一个提交按钮

<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>

然后在我的javascript代码我把这个

function doupload() {
    let data = document.getElementById("file").files[0];
    let entry = document.getElementById("file").files[0];
    console.log('doupload',entry,data)
    fetch('uploads/' + encodeURIComponent(entry.name), {method:'PUT',body:data});
    alert('your file has been uploaded');
    location.reload();
};

如果你喜欢StackSnippets…

函数doupload() { let data = document.getElementById("file").files[0]; let entry = document.getElementById("file").files[0]; console.log(“doupload”、条目、数据) fetch('uploads/' + encodeURIComponent(entry.name), {method:'PUT',body:data}); 警报('您的文件已上传'); }; <input type="file" name="file" id="file"> <button onclick="doupload()" name="submit">上传文件</button> .

PUT方法与POST方法略有不同。在这种情况下,在web服务器的chrome, POST方法是不实现的。

测试与web服务器的chrome - https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en

注意:当你使用chrome浏览器的web服务器时,你需要进入高级选项并勾选“启用文件上传”选项。如果您不这样做,您将得到一个不允许的错误。