Source : Baoyu BLOG
1. Je vais expliquer petit à petit le principe du téléchargement sans composant avec un exemple Le HTML client est le suivant. Pour parcourir les pièces jointes téléchargées, nous transmettons l'élément <input type="file">, mais veillez à définir l'attribut enctype du formulaire sur "multipart/form-data" :
<form method="post" action="upload.asp" enctype="multipart/form-data">
<étiquette>
<input type="file" name="file1" />
</étiquette>
<br />
<input type="text" name="filename" value="nom de fichier par défaut"/>
<br />
<input type="submit" value="Soumettre"/>
<input type="reset" value="Réinitialiser"/>
</form>
Dans le programme asp en arrière-plan, il était très facile d'obtenir les données ASCII soumises par le formulaire. Mais si vous avez besoin d'obtenir le fichier téléchargé, vous devez utiliser la méthode BinaryRead de l'objet Request pour le lire. La méthode BinaryRead effectue la lecture binaire d'un nombre spécifié d'octets du flux d'entrée actuel. Une chose à noter est qu'une fois la méthode BinaryRead utilisée, les collections Request.Form ou Request.QueryString ne peuvent plus être utilisées. Combinées avec la propriété TotalBytes de l'objet Request, toutes les données soumises par le formulaire peuvent être converties en binaire, mais ces données sont toutes codées. Tout d'abord, examinons comment ces données sont codées. Y a-t-il des règles à suivre ? Dans le code, nous convertissons le binaire lu par BinaryRead en texte et le publions dans le fichier upload.asp en arrière-plan (remarque). Ne téléchargez pas de fichiers volumineux dans cet exemple, sinon le navigateur pourrait planter :
<%
Dim biData, PostData
Taille = Requête.TotalBytes
biData = Request.BinaryRead (Taille)
PostData = BinaryToString (biData, Taille)
Response.Write "<pre>" & PostData & "</pre>" 'Utilisez pre et affichez le format tel quel
'Convertir le flux binaire en texte à l'aide de RecordSet
Fonction BinaryToString(biData,Size)
Const adLongVarChar = 201
Définir RS = CreateObject("ADODB.Recordset")
RS.Fields.Append "mBinary", adLongVarChar, taille
RS.Ouvert
RS.AddNew
RS("mBinary").AppendChunk(biData)
RS.Mise à jour
BinaryToString = RS("mBinary").Valeur
RS.Fermer
Fonction de fin
%>
Par souci de simplicité, téléchargez le fichier texte le plus simple (G:homepage.txt, avec le contenu « Baoyu : http://www.webuc.net ») pour le tester. Conservez la valeur par défaut « nom de fichier par défaut » dans le fichier. nom de fichier de la zone de texte Soumettez et voyez le résultat :
--------------------------------7d429871607fe.
Disposition du contenu : form-data ; nom="file1" ; nom de fichier="G:homepage.txt"
Type de contenu : texte/plain
Baoyu : http://www.webuc.net
--------------------------7d429871607fe
Contenu-Disposition : formulaire-données ; nom="nom de fichier"
nom de fichier par défaut
-----------------------------7d429871607fe--
On constate que pour les éléments du formulaire, "----- --------------------------7d429871607fe" De telles limites sont utilisées pour séparer les pièces en morceaux, et il y a des informations de description au début de chaque pièce. , par exemple : Content- Disposition: form-data; name="filename", dans les informations de description, vous pouvez connaître le nom de l'élément de formulaire via name="filename". S'il y a un contenu comme filename="G:homepage.txt", cela signifie qu'il s'agit d'un fichier téléchargé, alors les informations de description auront une ligne supplémentaire Content-Type: text/plain pour décrire. le type de contenu du fichier. Les informations de description et les informations sur le corps sont séparées par des sauts de ligne.
Eh bien, c'est fondamentalement clair. Selon cette règle, nous savons comment séparer les données et traiter les données séparées. Cependant, nous avons presque négligé un problème, qui est la valeur limite ("-------" dans ce qui précède. exemple) Comment -----------------------7d429871607fe") l'a-t-il su ? Cette valeur limite est différente à chaque fois que vous la téléchargez. Heureusement, elle peut être obtenue via Request.ServerVariables("HTTP_CONTENT_TYPE") dans asp. Par exemple, dans l'exemple ci-dessus, le contenu de HTTP_CONTENT_TYPE est : "multipart/form-data; border=-- ----------------7d429871607fe", avec cela, nous pouvons non seulement déterminer si enctype="multipart/form- data " (s'il n'est pas utilisé, il n'est pas nécessaire de l'exécuter ci-dessous), vous pouvez également obtenir la limite de valeur limite=---------------------- ----- 7d429871607fe. (Remarque : la valeur limite obtenue ici a moins de "--" au début que la valeur limite ci-dessus. Il est préférable de l'ajouter.)
Quant au processus d'analyse des données, je n'entrerai pas dans les détails. n'est rien de plus que d'utiliser des fonctions telles que InStr et Mid pour séparer les données souhaitées.
2. Lors du téléchargement en morceaux, la progression de l'enregistrement doit refléter la barre de progression en temps réel. L'essentiel est de savoir quelle quantité de données le serveur actuel a obtenue en temps réel ? En repensant au processus de téléchargement, nous l'implémentons via Request.BinaryRead (Request.TotalBytes). Pendant le processus de requête, nous ne pouvons pas savoir combien de données le serveur actuel a obtenu. Nous ne pouvons donc utiliser une solution de contournement que si nous pouvons diviser les données obtenues en morceaux, puis en fonction du nombre de blocs qui ont été téléchargés, nous pouvons calculer la taille actuellement téléchargée ! C'est-à-dire que si 1K correspond à 1 bloc, alors le flux d'entrée du téléchargement de 1 Mo sera divisé en 1024 blocs pour obtenir. Par exemple, si j'ai obtenu 100 blocs, cela signifie que 100 Ko ont été téléchargés. Lorsque j'ai proposé le blocage, beaucoup de gens ont trouvé cela incroyable car ils ignoraient que la méthode BinaryRead pouvait non seulement lire la taille spécifiée, mais aussi lire en continu.
Écrivez un exemple pour vérifier l'intégrité de la lecture des blocs, basé sur l'exemple présenté tout à l'heure (notez que cet exemple ne télécharge pas de fichiers volumineux, sinon cela pourrait provoquer un crash du navigateur) :
<%
Dim biData, PostData, TotalBytes, ChunkBytes
ChunkBytes = 1 * 1024 ' La taille du fragment est de 1 Ko
TotalBytes = Request.TotalBytes 'Taille totale
PostData = "" ' Données converties en type texte
ReadedBytes = 0 'Initialisé à 0
'Lire en morceaux
Faire pendant que ReadedBytes < TotalBytes
biData = Request.BinaryRead(ChunkBytes) 'Chronum actuel
PostData = PostData & BinaryToString(biData,ChunkBytes) 'Convertissez le morceau actuel en texte et divisez-le
ReadedBytes = ReadedBytes + ChunkBytes 'Taille de lecture de l'enregistrement
Si ReadedBytes > TotalBytes Alors ReadedBytes = TotalBytes
Boucle
Response.Write "<pre>" & PostData & "</pre>" ' Utiliser pre et afficher le format tel quel
' Convertir un flux binaire en texte
Fonction BinaryToString(biData,Size)
Const adLongVarChar = 201
Définir RS = CreateObject("ADODB.Recordset")
RS.Fields.Append "mBinary", adLongVarChar, taille
RS.Ouvert
RS.AddNew
RS("mBinary").AppendChunk(biData)
RS.Mise à jour
BinaryToString = RS("mBinary").Valeur
RS.Fermer
Fonction de fin
%>
Essayez de télécharger le fichier texte tout à l'heure. Les résultats de sortie prouvent que le contenu lu en blocs est complet, et dans la boucle While, nous pouvons enregistrer l'état actuel dans l'application à chaque fois qu'elle boucle, puis nous pouvons accéder au Application pour obtenir dynamiquement la barre de progression du téléchargement.
Également : dans l'exemple ci-dessus, l'épissage de chaînes est utilisé. Si vous souhaitez épisser des données binaires, vous pouvez utiliser la méthode Write de l'objet ADODB.Stream. L'exemple de code est le suivant :
Définissez bSourceData = createobject("ADODB.Stream". )
bSourceData.Open
bSourceData.Type = 1 'Binaire
Faire pendant que ReadedBytes < TotalBytes
biData = Request.BinaryRead (ChunkBytes)
bSourceData.Write biData 'Utiliser directement la méthode d'écriture pour écrire le flux de fichier actuel dans bSourceData
ReadedBytes = ReadedBytes + ChunkBytes
Si ReadedBytes > TotalBytes Alors ReadedBytes = TotalBytes
Application("ReadedBytes") = ReadedBytes
Boucle
3. Enregistrez le fichier téléchargé. Obtenez les données soumises via Request.BinaryRead Après avoir séparé le fichier téléchargé, la méthode de sauvegarde est différente selon le type de données :
pour les données binaires, vous pouvez enregistrer le flux binaire directement via la méthode SaveToFile du. Objet ADODB.Stream.
Pour les données texte, vous pouvez enregistrer les données texte dans un fichier via la méthode Write de l'objet TextStream.
Les données texte et les données binaires peuvent être facilement converties entre elles. Pour le téléchargement de petits fichiers, il n'y a fondamentalement aucune différence entre les deux. Cependant, il existe encore quelques différences lors de l'enregistrement entre les deux méthodes. Pour l'objet ADODB.Stream, toutes les données doivent être chargées avant de pouvoir être enregistrées sous forme de fichier. Par conséquent, le téléchargement de fichiers volumineux à l'aide de cette méthode occupera beaucoup de mémoire. et pour l'objet TextStream, Une fois le fichier créé, vous pouvez en écrire une partie à la fois et l'écrire plusieurs fois. L'avantage est qu'il n'occupera pas l'espace mémoire du serveur. Combiné avec le principe d'obtention de données. blocs analysés ci-dessus, nous pouvons écrire chaque élément de données téléchargées dans le fichier central. Une fois, j'ai fait une expérience et j'ai téléchargé un fichier de plus de 200 Mo sur la même machine. En utilisant la première méthode, la mémoire n'a cessé d'augmenter, cela a directement indiqué que la mémoire virtuelle de l'ordinateur était insuffisante. même si la barre de progression indique que le fichier a été téléchargé, au final, le fichier n'est toujours pas enregistré. En utilisant cette dernière méthode, il n’y a pratiquement aucun changement dans la mémoire pendant le processus de téléchargement.
4. Problèmes non résolus J'ai vu Bestcomy sur le blog décrivant que son composant de téléchargement Asp.Net peut être indépendant de Sever.SetTimeOut, mais dans Asp, je n'ai pas pu le faire. Pour télécharger des fichiers volumineux, je ne peux utiliser que Server.SetTimeOut. être fixé à une valeur très élevée. Je ne sais pas s'il existe une meilleure solution.
Si nous utilisons la méthode Write de l'objet TextStream lors de l'enregistrement d'un fichier, alors si l'utilisateur interrompt le transfert du fichier lors du téléchargement, la partie du fichier qui a été téléchargée est toujours là. Ce serait formidable si le téléchargement pouvait reprendre. Le problème clé est que même si la méthode Request.BinaryRead peut lire par blocs, elle ne peut pas sauter une certaine section de lecture !
5. Conclusion Le principe est fondamentalement expliqué clairement, mais le code lui-même est beaucoup plus compliqué que cela. Il y a de nombreuses questions à considérer. La partie la plus difficile est l'analyse des données acquises. Analysez s'il appartient aux informations de description. L'élément du formulaire est toujours un fichier téléchargé et si le fichier a été téléchargé...
Je pense que sur la base de la description ci-dessus, vous pouvez également développer votre propre composant de téléchargement puissant sans composant. Je pense que de plus en plus de gens ne se soucient que du code et ne savent pas comment l'écrire eux-mêmes. Peut-être qu'ils n'ont pas le temps, peut-être que le niveau n'est pas suffisant, et c'est juste devenu une habitude... J'ai. vu trop de technologies sur CSDN Essai en huit parties - un paragraphe de description, puis tout le code. Apprendre à un homme à pêcher n'est pas aussi bon que lui apprendre à pêcher. Si je vous donne un code, vous ne réfléchirez peut-être pas au pourquoi et vous l'utiliserez simplement la prochaine fois. Lorsque vous rencontrerez un problème similaire, vous ne saurez toujours pas pourquoi. J'espère que cet article pourra aider davantage de personnes à apprendre quelque chose, et le plus important est d'« éclairer » quelque chose !