JavaScript:上传文件

Yum*_*hMì 163 javascript file-upload

假设我在页面上有这个元素:

<input id="image-file" type="file" />
Run Code Online (Sandbox Code Playgroud)

这将创建一个按钮,允许网页用户通过浏览器中的"文件打开..."对话框选择文件.

假设用户单击所述按钮,在对话框中选择一个文件,然后单击"确定"按钮关闭对话框.

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

document.getElementById("image-file").value
Run Code Online (Sandbox Code Playgroud)

现在,假设服务器在URL"/ upload/image"处理多部分POST.

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

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

Mat*_*all 90

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

<form enctype="multipart/form-data" action="/upload/image" method="post">
    <input id="image-file" type="file" />
</form>
Run Code Online (Sandbox Code Playgroud)

如果您确实想要在后台上传图像(例如,不提交整个表单),您可以使用ajax:

  • @KajMagnus,你可能意味着'上传'但不小心说'upvote' (30认同)
  • 现在可以通过Javascript和Ajax进行upvote,请参阅:http://stackoverflow.com/a/10811427/694469(我没有downvote). (11认同)

Kam*_*ski 48

PURE JS

使用以下代码:

let photo = document.getElementById("image-file").files[0];
let formData = new FormData();

formData.append("photo", photo);
fetch('/upload/image', {method: "POST", body: formData});
Run Code Online (Sandbox Code Playgroud)
  • 在serwer端,您可以阅读自动包含在上述请求中的原始文件名(和其他信息).
  • 您无需使用Content-Type- 这将由浏览器自动设置.
  • 而不是multipart/form-data你可以使用完整的地址/upload/image.
  • 您可以包含其他数据(json),例如http://.../upload/image以这种方式请求:let user = {name:'john', age:34}
  • 此解决方案适用于所有主流浏览器.

下面是带有错误处理的片段,它发送文件,但SO片段有一些错误处理问题 - xhr.status为零(而不是404),这类似于我们从本地光盘上的文件运行脚本的情况- 所以我也提供js小提琴版本,在这里显示正确的http错误代码.

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));  
    
    try {
       let r = await fetch('/upload/image', {method: "POST", body: formData}); 
       console.log('HTTP response code:',r.status); 
    } catch(e) {
       console.log('Huston we have problem...:', e);
    }
    
}
Run Code Online (Sandbox Code Playgroud)
<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)
Run Code Online (Sandbox Code Playgroud)

UPDATE

您也可以使用await-try-catch选择fetch(这里我们也有SO片段的错误处理问题,但是在jsfiddle版本中404错误4xx/5xx根本没有丢弃,但我们可以读取包含代码的响应状态)

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);
Run Code Online (Sandbox Code Playgroud)

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.open("POST", '/upload/image');    
    xhr.send(formData);
}
Run Code Online (Sandbox Code Playgroud)
<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>)
Run Code Online (Sandbox Code Playgroud)


kvz*_*kvz 6

作为其创建者,我有偏见;),但您也可以考虑使用https://uppy.io之类的东西。它可以在不离开页面的情况下进行文件上传,并提供一些额外的功能,例如拖放,在浏览器崩溃/网络不稳定时恢复上传,以及从例如Instagram导入。它也是开源的,不依赖jQuery或类似的东西。


Eth*_*ien 6

我已经尝试这样做有一段时间了,但这些答案都不适合我。我就是这样做的。

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

<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>
Run Code Online (Sandbox Code Playgroud)

然后在我的 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();
};
Run Code Online (Sandbox Code Playgroud)

如果您喜欢 StackSnippets...

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

方法PUT与方法略有不同POST。在这种情况下,在 Chrome 的 Web 服务器中,该POST方法未实现。

使用 Chrome 网络服务器进行测试 - https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en

注意 - 当使用 Chrome 网络服务器时,您需要进入高级选项并选中“启用文件上传”选项。如果不这样做,您将收到不允许的错误。