web-dev-qa-db-ja.com

JavaScript:ファイルをアップロードする

この要素がページにあるとしましょう。

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

これにより、WebページのユーザーがブラウザのOSの[ファイルを開く...]ダイアログでファイルを選択できるボタンが作成されます。

ユーザーがこのボタンをクリックし、ダイアログ内のファイルを選択してから、「OK」ボタンをクリックしてダイアログを閉じるとします。

選択したファイル名は次の場所に保存されています。

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

それでは、サーバーがURL「/ upload/image」でマルチパートPOSTを処理するとしましょう。

ファイルを "/ upload/image"に送信するにはどうすればいいですか?

また、ファイルのアップロードが完了したという通知を受け取るにはどうすればよいですか。

147
YummyBánhMì

Ajaxを使用してファイルをアップロードしようとしているのでなければ、フォームを/upload/imageに送信してください。

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

画像をバックグラウンドでアップロードしたい場合(フォーム全体を送信せずに)、ajaxを使用できます。

87
Matt Ball

ピュアJS

あなたは フェッチ をオプションで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(e) 
{
    let user = { name:'john', age:34 };
    let formData = new FormData();
    let photo = e.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);
    }
    
}
<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>

(スタックオーバーフロースニペットではエラー処理に問題がありますが、404エラーのための jsfiddleバージョン 4xx/5xxは をまったく投げていません コードを含む応答ステータスを読み取る)

旧スクールアプローチ - 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.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>

(スタックオーバーフローのスニペットは、エラー処理に問題があります - xhr.statusは(404ではなく)ゼロです。これは、 ローカルディスク のファイルからスクリプトを実行したときの状況に似ています私はまた適切なhttpエラーコード を示すjsフィドルバージョンをここに提供します

まとめ

  • サーバー側では、要求に自動的に含まれる元のファイル名(およびその他の情報)を読み取ることができます。
  • fetch(url,{headers:{"Content-Type": "multipart/form-data",...},...})req.setRequestHeader('Content-Type', 'multipart/form-data');を使う必要はありません - これはブラウザによって自動的に設定されます。
  • /upload/imageの代わりに、http://.../upload/imageのようにフルアドレスを使うことができます。
  • 追加のデータ(json)を含めることができます。このようにlet user = {name:'john', age:34}formData.append("user", JSON.stringify(user));
  • この解決策はすべての主要ブラウザで機能するはずです。
29

実際に画像をアップロードするための純粋なjavascriptの方法を探しているのであれば、2009年からの以下のチュートリアルはそれを正確に行う方法を教えてくれます:

http://igstan.ro/posts/2009-01-11-ajax-file-upload-with-pure-javascript.html

クッキーを有効にせずにフォーム送信に基本認証を追加したいと思ったときに私はこれに遭遇しました。例えば。あなたのファイル名、ファイルなどのフィールドを持つユーザー名/パスワードフィールドがあるとき。

お役に立てれば!

24
dwh

その作成者として私は偏っています;)しかし、 https://uppy.io のようなものを使用することも検討できます。それはページから移動せずにファイルのアップロードを行い、ドラッグ&ドロップのようないくつかのボーナスを提供し、ブラウザのクラッシュ/不安定なネットワークの場合にはアップロードを再開し、そしてインスタグラム。これもオープンソースであり、jQueryやそれに類するものには依存しません。

6
kvz