JavaScript:上传文件
Posted
技术标签:
【中文标题】JavaScript:上传文件【英文标题】:JavaScript: Upload file 【发布时间】:2011-08-01 01:44:30 【问题描述】:假设我在页面上有这个元素:
<input id="image-file" type="file" />
这将创建一个按钮,允许网页用户通过浏览器中的操作系统“文件打开...”对话框选择文件。
假设用户单击所述按钮,在对话框中选择一个文件,然后单击“确定”按钮关闭对话框。
所选文件名现在存储在:
document.getElementById("image-file").value
现在,假设服务器在 URL“/upload/image”处处理多部分 POST。
如何将文件发送到“/upload/image”?
另外,我如何收听文件上传完成的通知?
【问题讨论】:
javascript 不处理上传,因为它是服务器端的。服务器端脚本将接收文件,然后移动它。对于从临时文件夹到所需文件夹的 php。 i found a nice solution using PHP here 投票给 reopen 因为问题是关于 POJS(普通旧 javascript)而不是 jQuery。 【参考方案1】:除非您尝试使用 ajax 上传文件,否则只需提交表单到/upload/image
。
<form enctype="multipart/form-data" action="/upload/image" method="post">
<input id="image-file" type="file" />
</form>
如果您确实想在后台上传图片(例如不提交整个表单),您可以使用 ajax:
Asynchronous file upload (AJAX file upload) using jsp and javascript jQuery Ajax File Upload Ajax using file upload【讨论】:
或 iframe 0x0 大小,在其 src="" 内带有图像上传脚本,并使用 target="iframeId" 将表单发布到它,在 iframe src .load 事件上读取结果,该事件可以使用 jQuery 绑定例如。 现在实际上可以通过 Javascript 和 Ajax 进行投票,请参阅:***.com/a/10811427/694469(我没有投票)。 @KajMagnus,您的意思可能是“上传”,但不小心说了“点赞”【参考方案2】:纯 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://***.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://***.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
- 这将由浏览器自动设置(包括 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
此解决方案应适用于所有主流浏览器。
【讨论】:
formData === 表单提交enctype="multipart/form-data"
我收到错误net::ERR_ABORTED 405 (Method Not Allowed)
@HidaytRahman 当服务器没有为您的 url 实现 POST 方法时,通常会出现此错误
奇怪 - 根据您的标题,我认为我们不再需要服务器:D
我收到了POST http://localhost:8000/upload/image 404 (Not Found)
。在我的 React Node 测试项目的 /src 和 /public 下创建 /upload/image。【参考方案3】:
我一直在尝试这样做一段时间,但这些答案都不适合我。我就是这样做的。
我有一个选择文件和一个提交按钮
<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');
location.reload();
;
<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>
PUT
方法与POST
方法略有不同。在这种情况下,在 chrome 的 web 服务器中,POST
方法没有实现。
用 chrome 的 web 服务器测试 - https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en
注意-使用 chrome 的 web 服务器时,您需要进入高级选项并选中“启用文件上传”选项。如果你不这样做,你会得到一个不允许的错误。
【讨论】:
以上是关于JavaScript:上传文件的主要内容,如果未能解决你的问题,请参考以下文章