ディレクトリ
入門
私は最近、アップロードとダウンロードファイルする必要がウェブサイト上で働いていました。私が、私は小さな記事を書く必要があると思ったので、何人かの人々のために、苦しみの場所であると思われる(私の最後の記事があまりにも長い間されているので、長い時間が経過した)、両方の自分の子孫のために、また、他のもののために。
背景
私は、デジタル製品の販売を格納するアプリケーションを構築しています。持つすべてのフロントエンドVueJS で書かれたASP.NETコアバックエンドAPI ファイルおよび提供するための、SPAを。
コードを使用して
唯一簡単に各モジュールの機能ではなく、話題まで、すべてのコンテンツと混乱の詳細な説明を記述し、私がするように、コードは、説明するのは簡単です。
ご登録APIを
main.ts
インポートのAPI モジュールを
import api from './services/api'; -- this is my sites api
...
Vue.prototype.$api = api;
API-plugin.d.ts
$のAPI に接続変数のVue とアサインのAPI タイプ。
import { Api } from './services/api';
declare module 'vue/types/vue' {
interface Vue {
$api: Api;
}
}
export default Api;
ファイルのアップロード
私にはVueJS 組立、Iのデータ()は、サーバーに送信するファイルを保存するために使用される変数内部オブジェクトを作成します。
files: new FormData(),
私は、ファイルをアップロードするファイルを追加するハンドラメソッドに応答するユーザーを追加しました
handleFileUpload(fileList: any) {
this.files.append('file', fileList[0], fileList[0].name);
},
Vueのコンポーネントテンプレートは、ファイルの入力要素が含まれています
<input type="file" v-on:change="handleFileUpload($event.target.files)" />
提出
あなたの中のユーザー際に続いて、UI のアップロードをトリガー操作を実行する場合、私は私の呼ぶAPIを。
this.$api.uploadFile(this.files)
.then((response: <<YourResponseType>>) => {
this.hasError = false;
this.message = 'File uploaded';
}).catch((error) => {
this.hasError = true;
this.message = 'Error uploading file';
});
APIのサービスメソッド
上記ではアジサシの私に表示されて組み立て方法API サービスでこのメソッドを呼び出します。
public async uploadFile(fileData: FormData): Promise<<<YourResponseType>>> {
return await axios.post('/api/to/your/upload/handler', fileData, { headers: { 'Content-Type': 'multipart/form-data' } })
.then((response: any) => {
return response.data;
})
.catch((error: any) => {
throw new Error(error);
});
}
ASP.NETコアAPI の方法
独自の要件に応じてメソッドのコードは非常に異なっているが、基本的な構造はこのようになります。
[HttpPost("/api/to/your/upload/handler")]
[Consumes("multipart/form-data")]
public async Task<IActionResult> UploadHandler(IFormCollection uploads)
{
if (uploads.Files.Length <= 0) { return BadRequest("No file data"); }
foreach (var f in uploads.Files)
{
var filePath = "YourGeneratedUniqueFilePath";
using (var stream = System.IO.File.Create(filePath))
{
await file.CopyToAsync(stream);
}
}
return Ok();
}
ファイルのダウンロード
サーバ側からのスタートでは、あなたのAPIの方法を以下に示します。私が使用しているのでKestralをするので、私が使用することを選択したControllerBase.PhysicalFile()メソッドを、しかし、あなたのコントローラがあなたのニーズ、そしてコントローラと同様に、基本的なコントローラのメソッドそのリターンのために、より適しているかどうControllerBase.File() 。
私がアップロードしたエンティティに関連付けられている私のデータを格納しているので、それがによって要求されたID 要求値のダウンロードができますが、いずれかの方法それはスーツニーズを使用することができます。
[HttpGet("[action]")]
public async Task<IActionResult> GetFile(string id)
{
var dir = "GetOrBuildYourDirectoryString";
var fileName = "GetYourFileName";
var mimeType = GetMimeType(fileName);
var path = Path.Combine(dir, fileName);
return PhysicalFile(path, mimeType, version.FileName);
}
public string GetMimeType(string fileName)
{
var provider = new FileExtensionContentTypeProvider();
string contentType;
if (!provider.TryGetContentType(fileName, out contentType))
{
contentType = "application/octet-stream";
}
return contentType;
}
注:FileExtensionContentTypeProviderのからタイプMicrosoft.AspNetCore.StaticFiles NuGet パッケージ
Install-Package Microsoft.AspNetCore.StaticFiles -Version 2.2.0
クライアントAPIのダウンロード
サーバー上でこれを呼び出すにはGETFILE()メソッド、私たちのクライアントAPIのサービスは、公共のダウンロード方法のために必要です。これは、物事は少しトリッキー取得になるだろう。あなたは提供するサーバーと設定する必要があり/ またはdispositionヘッダの開示を。私は、単純な、それを維持したいので、これは、多少、この資料の範囲外です。
私は、このヘッダにアクセスするには、特別な手順を実行する必要はありませんが、私は必要なクライアントデータを抽出するために、いくつかの操作を実行する必要があります - 主にファイル名。残念ながら、このコードは特に良くありません。誰もがそれを改善する方法上の任意の提案を持っている場合、私に知らせてください。
public async downloadFile(id: string): Promise<void> {
return await axios.get('/api/download/getfile?id=' + id, { responseType : 'blob' } )
.then((response: any) => {
const disposition = response.headers['content-disposition'];
let fileName = '';
if (disposition && disposition.indexOf('attachment') !== -1) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
const fileUrl = window.URL.createObjectURL(new Blob([response.data]));
const fileLink = document.createElement('a');
fileLink.href = fileUrl;
fileLink.setAttribute('download', fileName);
document.body.appendChild(fileLink);
fileLink.click();
})
.catch((error: any) => {
throw new Error(error);
});
}
これは、ダイアログ、従来のブラウザの保存ローカルユーザーファイルをダウンロードして開くようにクライアントを設定します。
アップロードされたファイルを保護します
で上記のコードを考慮して「マニュアル」のダウンロードおよびアップロードファイルのプロセス、それは考えることができ、ブラウザのHTML で単純なファイルURLは、理想的な状況ではありません。私の例では、私は、ダウンロードディレクトリで処理するファイルをアップロードしました。
この保護するためには、「ダウンロード」ディレクトリを、私はしていたStartUp.cs設定ロジックの少量のメソッドにマッピングされます.NETのコア IApplicationBuilderのインスタンス。これは、この傍受しますURLを任意の要求と送信401 応答を。
app.Map("/downloads", subApp => {
subApp.Use(async (context, next) =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
});
});
アクセスしようとするとダウンロードディレクトリ内の人物ファイルが案内されますが、ブラウザはサーバからエラー応答を受信します。
私はあなたがこの方法では、いくつかの使用の簡単な説明を見つけることができます願っています。