[英]JavaScript: Upload file
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?另外,我如何收听文件上传完成的通知?
You can use fetch optionally 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)); 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)
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.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>)
SUMMARY概括
filename
formData parameter.filename
formData 参数中的浏览器请求中。Content-Type
to multipart/form-data
- this will be set automatically by browser (which will include the mandatory boundary
parameter ).Content-Type
设置为multipart/form-data
- 这将由浏览器自动设置(其中将包括强制boundary
参数)。/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)./upload/image
你可以使用像http://.../upload/image
这样的完整地址(当然这两个地址都是任意的,并且取决于服务器 - 与参数method
相同的情况 - 通常在服务器上使用“POST”用于文件上传,但有时可以使用“PUT”或其他)。multiple
attribute: <input multiple type=... />
, and attach all chosen files to formData in similar way (eg photo2=...files[2];
... formData.append("photo2", photo2);
)multiple
属性: <input multiple type=... />
,并以类似的方式将所有选择的文件附加到 formData(例如photo2=...files[2];
... formData.append("photo2", photo2);
)let user = {name:'john', age:34}
in this way: formData.append("user", JSON.stringify(user));
let user = {name:'john', age:34}
以这种方式: formData.append("user", JSON.stringify(user));
fetch
using AbortController
, for old approach by xhr.timeout= milisec
AbortController
fetch
,对于旧方法通过xhr.timeout= milisec
Unless you're trying to upload the file using ajax, just submit the form to /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 (eg without submitting the whole form), you can use ajax:如果您确实想在后台上传图片(例如,不提交整个表单),您可以使用 ajax:
As its creator I'm biased ;) but you could also consider using something like https://uppy.io . 作为其创建者,我有偏见;),但您也可以考虑使用https://uppy.io之类的东西。 It does file uploading without navigating away from the page and offers a few bonuses like drag & drop, resuming uploads in case of browser crashes/flaky networks, and importing from eg Instagram.
它可以在不离开页面的情况下进行文件上传,并提供一些额外的功能,例如拖放,在浏览器崩溃/网络不稳定的情况下恢复上传以及从例如Instagram导入。 It's also open source and does not rely on jQuery or anything like that.
它也是开源的,不依赖jQuery或类似的东西。
I have been trying to do this for a while and none of these answers worked for me.我一直在尝试这样做一段时间,但这些答案都不适合我。 This is how I did it.
我就是这样做的。
I had a select file and a submit button我有一个选择文件和一个提交按钮
<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>
Then in my javascript code I put this然后在我的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();
};
If you like StackSnippets...如果你喜欢 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>
The PUT
method is slightly different than the POST
method. PUT
方法与POST
方法略有不同。 In this case, in web server for chrome, the POST
method is not implemented.在这种情况下,在 chrome 的 Web 服务器中,
POST
方法没有实现。
Tested with web server for chrome - https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en使用 chrome 的网络服务器测试 - https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en
Note- When using web server for chrome you need to go into advanced options and check the option 'enable file upload'.注意 - 使用 chrome 的 Web 服务器时,您需要进入高级选项并选中“启用文件上传”选项。 If you do not, you will get an error for not allowed.
如果你不这样做,你会得到一个不允许的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.