私は仕事でそのような要求に遭遇しました。以前は、nodejs を使用してファイルをアップロードする方法しか知りませんでした。ブラウザの動作をシミュレートすることと同じです。 Google で検索したところ、ブラウザは http プロトコルを使用してデータをサーバーに送信しているだけであることがわかりました。具体的なプロトコルは、「RFC 1867 - Form-based File Upload in HTML」です。これは、フォーム フォームを通じてファイルをアップロードする方法です。ブラウザー プロトコルを使用すると、まずブラウザーがサーバーに送信するデータを確認でき、次に同じ方法でアップロード機能を実装できます。ファイルをアップロードするフォームについて言えば、誰もがそれに精通しているはずです:
<form action="http://www.qq.com/" method="post"> <input type="text" name="text1" /><br /> <input type="text" name="text2" /><br /> <input type="submit" /> </form>
送信時に、フィドラーを使用してパケットをキャプチャすると、そのようなデータがサーバーに送信されることがわかります:
POST http:/ /www.qq .com/ HTTP/1.1
ホスト: www.qq.com
Content-Length: 23
Content-Type: application/x-www-form-urlencoded charset=UTF-8
text1=hello&text2=世界
価値があります。Content-Type のデフォルトは application/x-www-form-urlencoded であるため、メッセージは URL エンコードされることに注意してください。たとえば、「Hello」は %E4%BD%A0%E5%A5%BD としてエンコードされます。
次に、フォームからアップロードする方法を見てみましょう。誰もがこれに精通しているはずです:
次に、「hello world」という単語だけを含む新しい Upload.txt テキスト ファイルを作成し、それをアップロードします。次に、fiddler を使用してパッケージをキャプチャします。送信されるデータはもう少し複雑です (キャッシュ制御や Cookie など、他の多くの無関係なリクエスト行は削除されています):
POST http://www.qq.com/ HTTP/1.1
Content-Length: 199
Content-Type: multipart/form-data; border=----WebKitFormBoundarywr3X7sXBYQQ4ZF5G
------WebKitFormBoundarywr3X7sXBYQQ4ZF5G
Content-Type: text/plain
hello world
-----WebKitFormBoundarywr3X7sXBYQQ4ZF5G--
RFC 1867 の定義に従って、境界データを生成する必要がありますこのデータは、コンテンツ内の他の場所に表示することはできません。これは、各ブラウザの生成アルゴリズムによって異なる場合があります。分離されたデータは、分離されたデータに配置されます。ヘッダーの Content-Type を指定してサーバーに送信します。これは、上記の Content-Type: multipart/form-data; border=----WebKitFormBoundarywr3X7sXBYQQ4ZF5G です。また、アップロードされたコンテンツは、区切り記号を使用して複数のセグメントに分割する必要があります。データの各セグメントにはファイルが含まれており、サーバーはこの名前を使用してファイルを受信します。この例では、ファイルの種類は text/plain です。 png画像はimage/pngです。ファイルタイプの後の空行は、アップロードされたファイルの内容です。この例では、理解しやすいようにテキストファイルがアップロードされているため、画像ファイルがアップロードされている場合は、その内容を直接表示できます。バイナリファイルです、fiddler 文字化けが表示されるだけです。 ファイルの内容が終了した後、空行と境界データが存在します。
送信フォーマットの詳細を理解したら、次はnodejsを使ってプログラミングをしていきます。簡単に言うと、フォーマットに従ってデータをサーバーに送信するだけです。
<form action="http://www.qq.com" method="post" enctype="multipart/form-data"> <input type="file" name="myfile" /> <input type="submit" value="submit" /> </form>
この記事の焦点は、プロトコルを理解し、それをコードで実装することです。コード構成には最適化のための領域が数多くあります。
最後に、ローカルの Apache で、アップロードしたファイルをテスト用に保存するための php を書きます:
const http = require('http'); const fs = require('fs'); //post地址为本地服务的一个php,用于测试上传是否成功 var options = { hostname: 'localhost', port: 80, path: '/get.php', method: 'POST' } //生成分隔数据 var boundaryKey = '----WebKitFormBoundaryjLVkbqXtIi0YGpaB'; //读取需要上传的文件内容 fs.readFile('./upload.txt', function (err, data) { //拼装分隔数据段 var payload = '--' + boundaryKey + '\r\n' + 'Content-Disposition:form-data; name="myfile"; filename="upload.txt"\r\n' + 'Content-Type:text/plain\r\n\r\n'; payload += data; payload += '\r\n--' + boundaryKey + '--'; //发送请求 var req = http.request(options, function (res) { res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('body:' + chunk); }); }); req.on('error', function(e) { console.error("error:"+e); }); //把boundary、要发送的数据大小以及数据本身写进请求 req.setHeader('Content-Type', 'multipart/form-data; boundary='+boundaryKey+''); req.setHeader('Content-Length', Buffer.byteLength(payload, 'utf8')); req.write(payload); req.end(); });
さらに、RFC 1867 によれば、一度に複数のファイルをアップロードする機能も使用できます。詳細については説明しませんが、必要に応じて RFC 1867 を参照してください。
上記は編集者によって紹介されたファイルアップロードの Node.js 実装です。ご質問があればメッセージを残してください。編集者がすぐに返信します。また、PHP 中国語 Web サイトをサポートしていただきありがとうございます。
ファイルアップロードの Node.js 実装に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。