JavaScript:上传文件

假设页面上有这个元素:

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

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

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

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

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

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

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

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

1001805 次浏览

除非你试图使用ajax上传文件,否则只需提交表格/upload/image即可。

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

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

纯JS

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

总结

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

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

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

<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…

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');
};
<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>

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

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

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