ホームページ >ウェブフロントエンド >jsチュートリアル >Koa2 ファイルのアップロードとダウンロードの例

Koa2 ファイルのアップロードとダウンロードの例

小云云
小云云オリジナル
2018-03-30 09:26:421912ブラウズ

この記事では、主に Koa2 ファイルのアップロードとダウンロードの例を紹介します。アップロードとダウンロードは、画像やその他のファイルなど、Web アプリケーションでは依然として比較的一般的です。 Koa には、機能を迅速に実装するのに役立つミドルウェアが多数あります。

ファイルアップロード

フロントエンドでファイルをアップロードする場合、フォームを通じてアップロードしますが、アップロードされたファイルはサーバー側の通常のパラメータのようにctx.request.bodyから取得することはできません。 koa-body ミドルウェアを使用してファイルのアップロードを処理し、リクエスト本文を ctx.request に入れることができます。


// app.js
const koa = require('koa');
const app = new koa();
const koaBody = require('koa-body');

app.use(koaBody({
  multipart: true,
  formidable: {
    maxFileSize: 200*1024*1024 // 设置上传文件大小最大限制,默认2M
  }
}));

app.listen(3001, ()=>{
  console.log('koa is listening in 3001');
})

ミドルウェアを使用すると、アップロードされたファイルの内容を ctx.request.body.files で取得できます。注意する必要があるのは、maxFileSize の設定です。そうしないと、アップロードされたファイルがデフォルトの制限を超えるとエラーが報告されます。

ファイルを受信したら、ファイルをディレクトリに保存し、フロントエンドに URL を返す必要があります。ノード内の処理は

  1. 読み取り可能なストリームの作成 const Reader = fs.createReadStream(file.path)

  2. 書き込み可能なストリームの作成 const Writer = fs.createWriteStream('upload/newpath.txt')

  3. 読み取り可能なストリームは、パイプreader.pipe(writer)を介して書き込み可能なストリームに書き込まれます


const router = require('koa-router')();
const fs = require('fs');

router.post('/upload', async (ctx){
 const file = ctx.request.body.files.file; // 获取上传文件
 const reader = fs.createReadStream(file.path); // 创建可读流
 const ext = file.name.split('.').pop(); // 获取上传文件扩展名
 const upStream = fs.createWriteStream(`upload/${Math.random().toString()}.${ext}`); // 创建可写流
 reader.pipe(upStream); // 可读流通过管道写入可写流
 return ctx.body = '上传成功';
})

このメソッドは、画像、テキストファイル、圧縮ファイルなどをアップロードするのに適しています。

ファイルダウンロード

koa-sendは、ファイルダウンロード機能を実装するために使用できる静的ファイルサービスミドルウェアです。


const router = require('koa-router')();
const send = require('koa-send');

router.post('/download/:name', async (ctx){
 const name = ctx.params.name;
 const path = `upload/${name}`;
 ctx.attachment(path);
  await send(ctx, path);
})

フロントエンドでダウンロードするには、window.open とフォーム送信の 2 つの方法があります。ここではより単純な window.open が使用されます。


<button onclick="handleClick()">立即下载</button>
<script>
 const handleClick = () => {
 window.open(&#39;/download/1.png&#39;);
 }
</script>

ここでのデフォルトの window.open は、新しいウィンドウを開いてフラッシュしてから閉じることですが、これはユーザーに良いエクスペリエンスを与えません。2 番目のパラメーター window.open('/download/1. png' , '_self'); したがって、現在のウィンドウに直接ダウンロードされます。ただし、これにより現在のページが URL に置き換えられ、ページがこのイベントをリッスンして何らかの操作を実行する場合、beforeunload などのページ イベントがトリガーされます。次に、非表示の iframe ウィンドウを使用して同じ効果を実現することもできます。


<button onclick="handleClick()">立即下载</button>
<iframe name="myIframe" style="display:none"></iframe>
<script>
 const handleClick = () => {
 window.open(&#39;/download/1.png&#39;, &#39;myIframe&#39;);
 }
</script>

バッチダウンロード

バッチダウンロードと単一ダウンロードの間に違いはなく、さらに数回ダウンロードを実行するだけです。これには本当に何の問題もありません。非常に多くのファイルを 1 つの圧縮パッケージにまとめて、この圧縮パッケージのみをダウンロードすれば、エクスペリエンスは向上すると思いませんか?

File Packaging

archiverは、Node.jsでクロスプラットフォームパッケージング機能を実現できるモジュールで、zip形式とtar形式をサポートしています。


const router = require(&#39;koa-router&#39;)();
const send = require(&#39;koa-send&#39;);
const archiver = require(&#39;archiver&#39;);

router.post(&#39;/downloadAll&#39;, async (ctx){
 // 将要打包的文件列表
 const list = [{name: &#39;1.txt&#39;},{name: &#39;2.txt&#39;}];
 const zipName = &#39;1.zip&#39;;
 const zipStream = fs.createWriteStream(zipName);
  const zip = archiver(&#39;zip&#39;);
  zip.pipe(zipStream);
 for (let i = 0; i < list.length; i++) {
 // 添加单个文件到压缩包
 zip.append(fs.createReadStream(list[i].name), { name: list[i].name })
 }
 await zip.finalize();
 ctx.attachment(zipName);
 await send(ctx, zipName);
})

フォルダー全体を直接パックする場合、各ファイルを走査して圧縮パッケージに追加する必要はありません


const zipStream = fs.createWriteStream(&#39;1.zip&#39;);
const zip = archiver(&#39;zip&#39;);
zip.pipe(zipStream);
// 添加整个文件夹到压缩包
zip.directory(&#39;upload/&#39;);
zip.finalize();

注: フォルダー全体をパックすると、生成された圧縮パッケージ ファイルはできませんそうでない場合は、継続的にパックされます。

中国語エンコードの問題

ファイル名に中国語が含まれている場合、予期しない状況が発生する可能性があります。そこで、アップロード時に漢字が含まれている場合は、encodeURI()でファイル名をエンコードして保存し、ダウンロード時にdecodeURI()で復号化します。


ctx.attachment(decodeURI(path));
await send(ctx, path);

ctx.attachment Content-Disposition を「attachment」に設定して、クライアントにダウンロードを求めるように指示します。デコードされたファイル名をダウンロードするファイルの名前として使用します。これにより、ローカルにダウンロードした場合でも中国語の名前が表示されます。

ただし、koa-sendのソースコードでは、decodeURIComponent()でファイルパスがデコードされます:


// koa-send
path = decode(path)

function decode (path) {
 try {
  return decodeURIComponent(path)
 } catch (err) {
  return -1
 }
}

このとき、デコード後、中国語を含むパスをダウンロードし、サーバーはエンコードされたパスを保存します, 当然、対応するファイルは見つかりません。

この問題を解決するには、デコードさせないでください。 koa-send ソース コードに触れたくない場合は、代わりに別のミドルウェア koa-sendfile を使用できます。


const router = require(&#39;koa-router&#39;)();
const sendfile = require(&#39;koa-sendfile&#39;);

router.post(&#39;/download/:name&#39;, async (ctx){
 const name = ctx.params.name;
 const path = `upload/${name}`;
 ctx.attachment(decodeURI(path));
  await sendfile(ctx, path);
})

関連する推奨事項:

koa2 に関する推奨記事 10 件

nodejs6 で koa2 フレームワークを使用するチュートリアル

nodejs で koa2 フレームワークを使用するチュートリアルの例を共有する

以上がKoa2 ファイルのアップロードとダウンロードの例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。