Partage de technologie

Comment télécharger des fichiers frontaux

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Méthode 1 : Téléchargement direct avec un tag

<a href="链接" >下载</a>
  • 1

Un lien de fichier (généralement un fichier sur le serveur). Ce lien est généralement saisi dans la barre d'adresse pour prévisualiser, pas pour télécharger une pièce jointe.

Si vous souhaitez le modifier en téléchargement de pièce jointe, vous pouvez choisir l'une des deux méthodes suivantes :
1. Traitement backend, ajoutez un en-tête de réponse au backend

res.setHeader('Content-Dispostion', 'attachment', 'name.pdf')

  • 1
  • 2

2. Ajoutez l'attribut download à la balise a

<a href="链接" download="文件名" >下载</a>
  • 1

Inconvénients de la première méthode :

Inconvénients : lors de l'utilisation de la balise a pour télécharger un fichier en JavaScript, le téléchargement du navigateur est déclenché directement via l'événement click de la balise a. L'en-tête de la requête ne peut pas être défini car il s'agit d'une simple requête GET. Si le téléchargement de ce fichier nécessite de porter un token, alors la balise a ne sera pas effective (la balise a ne peut pas porter le token) et deviendra un aperçu.
Solution : La balise a peut transporter des cookies, il existe donc une autre solution. Avant de télécharger le fichier, envoyez une demande pour obtenir un token temporaire et transportez-le via le cookie. Le téléchargement de la balise a est un téléchargement en streaming, qui effectuera les fichiers du serveur. comme de l'eau courante stocké sur le disque local, afin que le téléchargement puisse être vu directement et que le fichier ne soit pas mis en cache dans le navigateur.

Deuxième méthode de titre : utilisez XMLHttpRequest ou la requête API Fetch.

Écrivez une méthode pour télécharger (essentiellement, utilisez toujours la balise a pour télécharger)
Cette méthode peut être une requête ajax, qui peut transporter un jeton, puis convertir le fichier serveur demandé en blob, créer une balise a pour le téléchargement, créer un élément de lien virtuel et simuler un clic pour télécharger. Cette méthode occupera le thread frontal.


import fetch from 'isomorphic-fetch';
const exportFile = (url, options) => {
  const projectId = sessionStorage.getItem(PROJECT_ID);
  const downLoadURL = projectId ? BATCH_ACTION_URL_PREFIX.V2 : BATCH_ACTION_URL_PREFIX.V1;
  const defaultOptions = {
    credentials: 'same-origin',
  };
  const newOptions = { ...defaultOptions, ...options };
  if (
    newOptions.method === 'POST' ||
    newOptions.method === 'PUT' ||
    newOptions.method === 'DELETE'
  ) {
    const projectId = sessionStorage.getItem(PROJECT_ID);
    const appId = sessionStorage.getItem(APP_ID);
    const shopId = sessionStorage.getItem(SHOP_ID);
    const params = {};
    projectId && Object.assign(params, { projectId });
    appId && Object.assign(params, { appId });
    shopId && Object.assign(params, { shopId });
    newOptions.body = { ...newOptions.body, ...params };
    if (!(newOptions.body instanceof FormData)) {
      newOptions.headers = {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        ...newOptions.headers,
      };
    } else {
      // newOptions.body is FormData
      newOptions.headers = {
        Accept: 'application/json',
        ...newOptions.headers,
      };
    }
  }
  const token = window.localStorage.getItem(TOKEN);
  if (token) {
    newOptions.headers = {
      'X-Authorization': `Bearer ${token}`,
      ...newOptions.headers,
    };
  }
  const lang = localStorage.getItem(LOCALE_KEY);
  if (lang) {
    newOptions.headers = {
      'Accept-Language': lang,
      ...newOptions.headers,
    };
  }
  const requestURL = `${downLoadURL}/${url}`;
  return request(requestURL, newOptions).then(res => {
    let filename;
    if (res.headers) {
      filename = (
        res.headers.get('Content-Disposition') || res.headers.get('content-disposition')
      ).split('attachment;filename=')[1];
    }
    if (res.blob) {
      res.blob().then(blob => {
        var alink = document.createElement('a');
        alink.style.display = 'none';
        alink.target = '_blank';
        if (window.navigator && window.navigator.msSaveOrOpenBlob) {
          // 兼容IE/Edge
          window.navigator.msSaveOrOpenBlob(blob, filename);
        } else {
          alink.href = window.URL.createObjectURL(blob);
          alink.download = filename;
        }
        document.body.appendChild(alink);
        alink.click();
        URL.revokeObjectURL(alink.href); // 释放URL 对象
        document.body.removeChild(alink);
      });
      return res;
    } else {
      if (res.code === 0) {
        return res;
      } else {
        message.warning(res.message);
      }
    }
  });
};

export default exportFile;


export default function request(url: string, options: Object) {
  const defaultOptions = {
    credentials: 'same-origin',
  };
  const newOptions = { ...defaultOptions, ...options };
  if (
    newOptions.method === 'POST' ||
    newOptions.method === 'PUT' ||
    newOptions.method === 'DELETE' ||
    newOptions.method === 'PATCH'
  ) {
    if (!(newOptions.body instanceof FormData)) {
      newOptions.headers = {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        ...newOptions.headers,
      };
      newOptions.body = JSON.stringify(newOptions.body);
    } else {
      // newOptions.body is FormData
      newOptions.headers = {
        Accept: 'application/json',
        ...newOptions.headers,
      };
    }
  }

  return fetch(url, newOptions).then(response => checkStatus(response, url, options));
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

Inconvénients de la deuxième méthode :

**Si le fichier est petit, tout ira bien. Si le fichier est volumineux, vous cliquerez pour télécharger, mais il n'y aura aucune réponse après quelques minutes. Ce temps d'attente est nécessaire pour convertir le fichier. le côté serveur dans un blob (res.blob () Cela a pris très longtemps) avant que le téléchargement en streaming de la balise a ne soit effectué (c'est seulement ici que le reflet interactif du téléchargement a commencé à apparaître sur la page)