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 属性:&lt;input multiple type=... /&gt;,并以类似的方式将所有选择的文件附加到 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:上传文件的主要内容,如果未能解决你的问题,请参考以下文章

哪个javascript框架支持ajax方式的文件上传

js如何上传文件

上传时的默认文件格式。 jQuery 或 Javascript

JavaScript 文件上传大小验证

javascript之大文件分段上传断点续传

JavaScript上传大文件的三种解决方案