Loupe

Envoyer des fichiers larges WebAPI

Aujourd'hui je devais créer un programme qui envoie des fichier "large" sur un webService WebAPI.

Par défaut un site web ASP.Net MVC n'accepte pas de requête de plus 4 megas, or mes fichiers pouvaient être beaucoup plus grands (jusqu'a 2 gigas). Je ne voulais pas désactiver cette sécurité (de taille de 4megas par requête max) de peur d'ouvrir la porte à des attaques DDOS.

Je me suis donc tourné vers l'envoi d'un fichier en plusieur partie sur ma WebAPI.

Méthode divisant un tableau d'octet en plusieurs tableaux d'octets de même taille :

        private static List<byte[]> SplitArray(this byte[] bytes, int chunkSize)
        {
            List<byte[]> result = new List<byte[]>();
            int pos = 0;
            int remaining;

            while ((remaining = bytes.Length - pos) > 0)
            {
                byte[] block = new byte[Math.Min(remaining, chunkSize)];

                Array.Copy(bytes, pos, block, 0, block.Length);
                result.Add(block);
                pos += block.Length;
            }

            return result;
        }

Une fois le fichier divisé en plusieurs tableaux de bytes je l'envoie au serveur de la façon suivante :
 - Envoie d'un post pour récupérer l'identifiant de fichier
- Et envoie un à un des tableaux d'octect


Coté WebAPI je crée deux méthodes :

  1. Une méthode qui retournera au client un Id de fichier
  2. Une méthode permettant d'envoyer au serveur un tableau d'octet associé à un fichier

Crée une entrée dans le dictionaire contenant tout les fichiers en cours de chargement :

        [HttpPost]
        [Route("addFile")]
        public async Task<int> AddFileAsync()
        {

                var id =  await GENERE_UN_ID_UNIQUE;

                // Ajoute cet ID dans le tableau de fichier en cour de chargement.
                HttpRuntime.Cache[idArchive.ToString()]
                
                return id;

        }


Permet d'envoyer des parties de fichiers au serveur :

        [HttpPost]
        [Route("addchunk")]
        public async Task AddChunkAsync([FromUri] bool isLast, 
            [FromUri] int idArchive, [FromBody] byte[] data)
        {

                var datas = HttpRuntime.Cache[idArchive.ToString()] as List<byte[]>;
              
                if (datas.ContainsKey(idArchive))
                {
                    // Ajoute la partie de fichier dans la liste de byte array
                    datas[idArchive].Add(data);

                    if (isLast)
                    {
                        datas.Remove(idArchive);
                        var datas = _datas[idArchive];

                        // Fusionne les tableaux de bytes en un seul.
                        var array = MergeArrays(datas);
                        await SAUVEGARDE_LE_FICHIER_RECONTRUIT

                    }
                }
                else
                {
                    throw new Exception("Id of archive not found");
                }

        }

Fusionne plusieurs tableaux de bytes en un seul :

        /// <summary>
        /// Merges the arrays.
        /// </summary>
        /// <param name="arrays">The arrays.</param>
        /// <returns>merge arrays</returns>
        private byte[] MergeArrays(List<byte[]> arrays)
        {
            var bytes = new byte[arrays.Sum(a => a.Length)];
            var offset = 0;
            foreach (var array in arrays)
            {
                Buffer.BlockCopy(array, 0, bytes, offset, array.Length);
                offset += array.Length;
            }

            return bytes;
        }

 

Happy coding :)

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus