vue アップロード ダウンロード

目次

アップロード

ダウンロード

得る

役職

オブジェクト/ファイルストリーム

ダウンロード処理リターン

ファイルストリーム

axios.post

パッケージ axios

バックエンドはファイル ストリームを直接返し、ファイルを開いて [オブジェクト オブジェクト] としてダウンロードします。 res を res.data に変更するだけです。

1. リクエスト設定タイプresponseType: 'blob' (未設定の場合、開いたファイルが文字化けします)

2. 傍受要求があった場合(直接返すだけ)

3.ダウンロード

4. ダウンロードをリクエストする

関連基礎

Response.text() は、レスポンスのテキストデータを Promise オブジェクトとして取得します。

decodeURIComponent() デコード

エスケープ()エンコーディング

マイム

リクエストの取得と投稿

キャッシュ 

副作用操作、情報取得・表示操作

コンテンツの配置 

CORS (Cross-Origin Resource Sharing) クロスオリジンリソース共有

必須

プリフライト事前チェック

リクエストの分類

シンプルなリクエスト シンプルなリクエスト (プリフライトなし)

応用

サーバーがクロスドメインを設定していない場合、json は text/plain に偽装できます


アップロード

submitAddFile(){
            var formData = new FormData();
            formData.append('num', this.addType);
            formData.append('linkId',this.addId);
            formData.append('rfilename',this.addFileName);
            for(var i=0;i<this.addArr.length;i++){
                formData.append('fileUpload',this.addArr[i]);
            }
          let config = {
            headers: {
              'Content-Type': 'multipart/form-data',
              'Authorization': this.token
            }
          };
          this.axios.post(apidate.uploadEnclosure,formData,config)
            .then((response) => {
                if(response.data.info=="success"){this.$message({
                        type: 'success',
                        message: '附件上传成功!'
                    });
                }
            })
        }

Vue でファイルのアップロードとダウンロードの方法を実現 - Nuggets

ダウンロード

得る

//静态a标签
<a :href='"/user/downloadExcel"' >下载模板</a>

//动态创建a标签:
<div name="downloadfile" onclick="downloadExcel()">下载</div>
function downloadExcel() {
    let a = document.createElement('a')
    a.href ="/user/downloadExcel"
    a.click();
} 

//window
 function downloadExcel() {
    window.location.href = "/tUserHyRights/downloadUsersUrl";
} 

役職

オブジェクト/ファイルストリーム

ダウンロード処理リターン

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

export const download= (response: { data?: any; config?: AxiosRequestConfig }) => {
  console.log("response", response);
return new Promise((resolve, reject) => {
  const fileReader = new FileReader();
  fileReader.onload = function () {
    try {
      console.log("result:", this.result);
      const jsonData = JSON.parse((this as any).result); // 成功 说明是普通对象数据
      if (jsonData?.code !== 200) {
        errorMsgTips(jsonData?.message ?? "请求失败");
        reject(jsonData);
      }
    } catch (err) {
      // 解析成对象失败,说明是正常的文件流
      // responseType为blob,以便接收二进制数据。
      const blob = new Blob([response.data]);
      // 本地保存文件
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      const filename = response?.config.headers?.["content-disposition"]
        ?.split("filename*=")?.[1]
        ?.substr(7);
      link.setAttribute("download", decodeURI(filename));
      document.body.appendChild(link);
      link.click();
      resolve(response.data);
    }
  };
  fileReader.readAsText(response.data);
});

ファイルストリーム

axios.post

// Vue组件中的方法
methods: {
  downloadFile() {
    axios.post('/api/download', { /* 请求参数 */ }, { responseType: 'blob' })
      .then(response => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.style.display = 'none'
        link.href = url;
         const filename = response?.config.headers?.["content-disposition"]
           ?.split("filename*=")?.[1]
           ?.substr(7);
         link.setAttribute("download", decodeURI(filename));// 指定下载后的文件名,防跳转
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      })
      .catch(error => {
        // 处理错误
        console.error(error);
      });
  }
}

応答ヘッダーからファイル名を抽出する:Content-Disposition応答ヘッダーのフィールドの値が のような形式になっておりfilename*=UTF-8''example-file.txt、ファイル名が抽出されますexample-file.txt

パッケージ axios

バックエンドはファイル ストリームを直接返し、ファイルを開いて [オブジェクト オブジェクト] としてダウンロードします。 res をres.dataに変更するだけです。

1. リクエスト設定タイプresponseType: 'blob' (未設定の場合、開いたファイルが文字化けします)

import request from '@/utils/request'
import { AxiosRequestConfig, AxiosResponse } from 'axios'
const baseUrl: string = process.env.NODE_ENV === 'development' ? '/test' : ''
const mock: boolean = false

export const postQuery = (params: string): Promise<AxiosResponse> => {
  const url: string = mock ? `${baseUrl}/xxx:8081/otherIndexUpload/${params}` : `${baseUrl}/otherIndexUpload/${params}`
  console.log('post: ', url)
  return request({ url, method: 'post', responseType: 'blob' })
}

return request({
  url: '/data/wos/download',
  method: 'post',
  data: data,
  responseType: 'blob',
  timeout: 3000000,
  onDownloadProgress: function (progressEvent: ProgressEvent<EventTarget>): void {
    // 处理原生进度事件
    store.state.percent = ((progressEvent.loaded / progressEvent.total) * 100).toFixed(2)
    console.log(`下载进度:${store.state.percent}`)
    if (Number(store.state.percent) == 100) {
      store.commit('changeProgress')
    }
  }
})

2. 傍受要求があった場合(直接返すだけ)

import service from 'axios'
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';

// 响应拦截器
service.interceptors.response.use(
  (response: { data: any; config: AxiosRequestConfig }) => {
    const resData = response.data || {}
    if (response.config.responseType === 'blob') {
      return response
    }..
  },
  (error: AxiosError) => {
...
  }
)

export default service

3.ダウンロード

export const download = (res: AxiosResponse) => {
  var blob = new Blob([res.data], {
    type: "application/vnd.ms-excel;charset=utf-8",
  });
  var url = window.URL.createObjectURL(blob);
  var aLink = document.createElement("a");
  aLink.style.display = "none";
  //指定文件名,防止跳转
  aLink.download =decodeURIComponent(escape(res?.headers?.["content-disposition"]?.split("filename=")?.[1]))
  aLink.href = url;
  document.body.appendChild(aLink);
  aLink.click();
  document.body.removeChild(aLink);
}

4. ダウンロードをリクエストする

toDownloadTemplate() {
    console.log('下载模板')
     API.postQuery(`downloadTemplate/${this.wpReleId}`).then((res: any) => {
      if (res.data.type === "application/vnd.ms-excel") {
        download(res);
      } else {
         res.data.text().then((res: any) => {
          this.$message.warning(JSON.parse(res).msg)
         })
       }
    })
  }

関連基礎

Response.text() は、レスポンスのテキストデータを Promise オブジェクトとして取得します。

requestType が requestType に指定された後に適用されますが、応答の一部のコンテンツ タイプが responseType に適していません。

fetch('https://example.com/api/data')
  .then(response => response.text())
  .then(textData => {
    console.log(textData); // 输出响应的文本数据
  })
  .catch(error => {
    console.error(error);
  });

decodeURIComponent()デコード

この関数はエンコードされた文字列をデコードし、通常の内容を表示します。

escape()コーディング

この関数は、文字化けした文字列をエンコードして、特殊文字 (中国語など) が UTF-8 に従ってエンコードされるようにします。

バイナリ ラージ オブジェクト。BLOB は、画像、オーディオ、ビデオ ファイルなどのバイナリ データを保存するデータ型です。

マイム

多目的インターネット メール拡張子は、転送されるファイル性質と形式を示します。ファイルの種類を識別するには、HTTP ヘッダーまたは他のプロトコルに特定の文字列を指定します。

メインタイプはファイルの大規模なカテゴリを示します。

「application」はアプリケーションの種類を示します。

「text」はテキストの種類を示します。

「image」は画像の種類などを示します。

サブタイプは特定のファイル形式を表します。

「プレーン」とはプレーンテキストを意味し、

「vnd」はカスタムタイプを意味します

「vnd.ms-excel」: Microsoft Excel スプレッドシート ファイル。

リクエストの取得と投稿

POST: サーバーに情報を送信するために使用され、機能は GET に似ていますが、通常は POST を使用することをお勧めします。

GET: URI (Uniform Resource Identifier) によって識別されるリソースへのアクセスを要求するために使用され、URL を通じてサーバーに渡すことができます。

GET リクエストの場合、ブラウザはhttp ヘッダーとデータを一緒に送信し、サーバーは200 (データを返す) で応答します。

POST の場合、ブラウザは最初にヘッダーを送信し、サーバーは100 continueで応答し、ブラウザはデータを送信し、サーバーは200 ok (データを返す) で応答します。

良好なネットワーク環境の場合、1 つのパケットを送信する時間と 2 つのパケットを送信する時間の差は基本的に無視できます。

ネットワーク環境が劣悪な場合、2 つのパケットを使用する TCP はデータ パケットの整合性を検証する上で大きな利点があります。

GET は通常、情報のクエリに使用されるため、POST は通常、特定の変更操作のための特定の情報 (登録、ログインなどの個人情報)を送信するために使用されます。

したがって、ブラウザがロールバックしても GET は再度リクエストせず、POST はリクエストを再度送信します。

ブラウザがロールバックしても GET は再度リクエストを行わないため、POST はリクエストを再度送信します。

したがって、GET リクエストはブラウザによってアクティブにキャッシュされますが、POST はキャッシュされません。GET
       リクエストのパラメータを手動で設定した場合、パラメータはブラウザの履歴に完全に保持され、POST のパラメータはキャッシュされません。

GET リクエストのパラメータはブラウザ履歴に完全に保持されるため、
GET リクエストの URL で送信されるパラメータには長さの制限がありますが、POST には制限がありません。

GET パラメータはURL を介して渡されるため、POST はリクエストボディに配置されます。

したがって、ハイパーリンクのダウンロードはgetリクエストです

キャッシュ 

副作用操作、情報取得・表示操作

ファイルのダウンロードは副作用操作であり、リソースを取得するための通常の GET リクエストではありません。

ブラウザは通常、ファイルのダウンロードの応答は 1 回限りであり、再利用されないとみなします。

そのため、デフォルトでキャッシュされる get リクエストもキャッシュに保存されません。

ブラウザーがファイル コンテンツをキャッシュに保存することを選択した場合でも、通常は、それを長期的な永続キャッシュではなく、一時キャッシュ sessionStorage に保存しますlocalStorage

リクエストによって返されたファイルはブラウザのキャッシュに保存され、href を使用してダウンロードされます。つまり、get リクエストは常にキャッシュから宛先パスに一度移動されます。

ブラウザがロールバックしても GET は再度リクエストを行わないため、POST はリクエストを再度送信します。

したがって、GET リクエストはブラウザによってアクティブにキャッシュされるため、リクエストが再度行われた
場合、        GET リクエストのパラメータはブラウザ履歴に完全に保持され、POST 内のパラメータは保持されません。

最大経過時間の単位: 秒


POST リクエストには副作用 (サーバー上のデータの変更など) があるため、

したがって、ブラウザは通常、POST 応答結果をキャッシュせず、手動でキャッシュを設定します ( Cache-Control、Expires、Last-Modified、Content-Disposition )

コンテンツの配置 

  1. attachment: コンテンツを添付ファイルとしてダウンロードすることを意味します。
  2. inline: コンテンツをページに埋め込むことを示します。通常は、PDF、画像など非 HTML コンテンツを直接表示するために使用されます。
  3. form-data: 応答コンテンツがフォーム データであることを示します。通常、フォーム アップロード ファイルの場合に使用されます。

Content-Disposition:attachment; filename="example.pdf" は、応答コンテンツを添付ファイルとしてダウンロードする
attachmentことを意味します

filename="example.pdf"ファイル保存時のファイル名は「example.pdf」と指定します。

ブラウザは、宛先パスに書き込むときに処理するために、ファイル データの一部をメモリに一時的に保存する場合があります。

ただし、これはブラウザ キャッシュの一部ではなく、ファイル転送と書き込みのための一時的なストレージです。

CORS (Cross-Origin Resource Sharing) クロスオリジンリソース共有

ブラウザがクロスオリジン サーバーにXMLHttpRequestリクエストを送信できるようにすることで、 AJAX が同じオリジンでのみ使用できるという制限を克服します。

これは、クロスオリジン AJAX リクエストに対する基本的なソリューションであり、最も一般的に使用されるソリューションです。

必須

現在、すべてのブラウザがこの機能をサポートしており、IE ブラウザは IE10 よりも古いものにすることはできません。

CORS にはブラウザーとバックエンドの両方のサポートが必要です。IE 8 および 9 は XDomainRequest を通じて実装する必要があります

CORS は、サーバー側で Access-Control-Allow-Origin を設定することで有効にできます。この属性は、どのドメイン名がリソースにアクセスできるかを示します。ワイルドカードが設定されている場合は、すべての Web サイトがリソースにアクセスできることを意味します。

プリフライト事前チェック

プリフライト リクエストとは、ブラウザがクロスドメイン リクエストを送信する前に、最初にOPTIONS リクエストを送信して、実際のリクエストを受け入れるかどうかをサーバーに尋ねることを意味します。

プリフライト リクエストは主に、カスタム リクエスト ヘッダーを含むものや単純でないヘッダー フィールドを使用するものなど、複雑なリクエストのセキュリティ検証に使用されます。

リクエストの分類

CORS は単純なリクエスト、単純でない/複雑なリクエストに分かれています

シンプルなリクエスト シンプルなリクエスト (プリフライトなし)

以下の2つの条件を同時に満たしていれば、簡単なリクエストです。

条件 1: 次のいずれかの方法を使用します。

  • 得る
  • 役職

条件 2: 許可されたカスタム リクエスト ヘッダー (例: X-PINGOTHER) に加えて、リクエスト ヘッダーには、Accept、Accept-Language、Content-Language、Content-Type、Range などのいくつかの単純なヘッダー フィールドのみが含まれています。

Content-Type の値は、次の 3 つのいずれかに制限されます。

  • テキスト/プレーン
  • multipart/form-data (キーと値のペアのデータ)
  • application/x-www-form-urlencoded ( URLエンコード) (デフォルト)

application/xml、text/xml、text/html、text/plain の違い

1. text/html はhtml 形式のテキスト です。

2. text/plain はプレーンテキストです ( XSS脆弱性を効果的に回避できます)

3. Text/xml は、xml ヘッダーで指定されたエンコード形式を無視し、デフォルトで us- asciiエンコードを採用します。

4. application/xml は、xml ヘッダーで指定されたエンコード形式に従ってエンコードされます。

リクエスト内のXMLHttpRequestUploadオブジェクトにはイベントリスナーが登録されていません。

XMLHttpRequestUpload オブジェクトには、XMLHttpRequest.upload プロパティを使用してアクセスできます。

GET /cors? HTTP/1.1
Host: localhost:2333
Connection: keep-alive
Origin: http://localhost:2332
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Referer: http://localhost:2332/CORS.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
If-None-Match: W/"1-NWoZK3kTsExUV00Ywo1G5jlUKKs"

サーバー側で Access-Control-Allow-Origin を設定するだけで済みます (これらのドメイン名に対するリクエストが受け入れられることを示します (* すべて) )

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

Access-Control-Allow-Methods: 許可される HTTP メソッドを指定します。たとえば、Access-Control-Allow-Methods: GET, POST, PUTGET、POST、および PUT メソッドが許可されることを示します。

Access-Control-Allow-Headers: 許可される HTTP ヘッダー フィールドを指定します。たとえば、Access-Control-Allow-Headers: Content-Type, AuthorizationContent-Type フィールドと Authorization フィールドが許可されることを示します。

Access-Control-Max-Age: プリフライト リクエスト (OPTIONS リクエスト) のキャッシュ時間を指定して、プリフライト リクエストが頻繁に送信されることを回避します。

Access-Control-Allow-Credentials: ターゲット ドメインへの資格情報 (Cookie など) の送信を許可するかどうかを示します。true に設定すると、送信が許可されることを意味します。

Access-Control-Expose-Headers は、クロスオリジン要求でアクセス可能な追加の応答ヘッダー フィールドを指定するために使用される CORS (Cross-Origin Resource Sharing) 応答ヘッダー フィールドです。

Access-Control-Expose-Headers を使用すると、サーバーは追加の応答ヘッダー フィールドを指定できます。これはブラウザーによって解放され、JavaScript コードがアクセスできるようになります。

ブラウザーがクロスドメイン要求を開始すると、セキュリティ上の理由により、一部のデフォルトの応答ヘッダー フィールド (Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma など) のみにアクセスできます。他のカスタム応答ヘッダー フィールドには、デフォルトではアクセスできません。

応用

サーバーがクロスドメインを設定していない場合、json は text/plain に偽装できます

原理:

事前チェックをバイパスするための単純なリクエストとしてラップされています。ただし、一部のクライアントまたはプロキシは依然として事前チェックを行っています

安全性:

ブラウザーの JSON 応答に対するデフォルトの処理メカニズムは、JSON 応答を自動的に解析して JavaScript オブジェクトに変換します。

ブラウザーが応答を受信すると、応答の Content-Type がapplication/jsonであるか、Content-Type が指定されていない場合、ブラウザーは自動的に応答本文をJSON、 JavaScript オブジェクトに解析し、悪意のあるコードが実行される可能性があり、セキュリティが低下する可能性があります。脆弱性または攻撃。

JSON 応答を text/plain としてマスカレードすることにより、応答を JavaScript オブジェクトに自動的に解析するブラウザのデフォルト動作を回避できます。

このように、JavaScript コードはデータのセキュリティと正確性を確保するために応答を手動で解析する必要があります。このマスカレードにより、応答の自動解析による潜在的なセキュリティ リスクに対する追加のセキュリティ層が提供されます。

//请求头
GET /example HTTP/1.1
Host: example.com
Accept: text/plain
//响应头
HTTP/1.1 200 OK
Content-Type: text/plain
//响应体
{"foo": "bar"}

クロスオリジン リソース共有 (CORS) - HTTP | MDN

クロスオリジン リソース共有 (CORS) - HTTP | MDN

おすすめ

転載: blog.csdn.net/qq_28838891/article/details/131443175