Quelle: Baoyu BLOG
1. Ich werde das Prinzip des komponentenlosen Uploads Stück für Stück anhand eines Beispiels erläutern. Das Client-HTML lautet wie folgt. Um hochgeladene Anhänge zu durchsuchen, übergeben wir das Element <input type="file">, stellen aber sicher, dass das enctype-Attribut des Formulars auf „multipart/form-data“ gesetzt ist:
<form method="post" action="upload.asp" enctype="multipart/form-data">
<Beschriftung>
<input type="file" name="file1" />
</label>
<br />
<input type="text" name="filename" value="default filename"/>
<br />
<input type="submit" value="Submit"/>
<input type="reset" value="Reset"/>
</form>
Im Hintergrund-ASP-Programm war es früher sehr einfach, die vom Formular übermittelten ASCII-Daten abzurufen. Wenn Sie jedoch die hochgeladene Datei benötigen, müssen Sie sie mit der BinaryRead-Methode des Request-Objekts lesen. Die BinaryRead-Methode führt ein binäres Lesen einer angegebenen Anzahl von Bytes aus dem aktuellen Eingabestream durch. Beachten Sie, dass nach Verwendung der BinaryRead-Methode die Request.Form- oder Request.QueryString-Auflistungen nicht mehr verwendet werden können. In Kombination mit der TotalBytes-Eigenschaft des Request-Objekts können alle vom Formular übermittelten Daten in Binärdaten konvertiert werden, diese Daten sind jedoch alle codiert. Schauen wir uns zunächst an, wie diese Daten codiert werden. Gibt es Regeln, die befolgt werden müssen? Im Code konvertieren wir die von BinaryRead gelesene Binärdatei in Text und geben sie im Hintergrund aus (Hinweis). Laden Sie in diesem Beispiel keine großen Dateien hoch, da sonst der Browser abstürzen kann):
<%
Dimmen Sie biData, PostData
Größe = Request.TotalBytes
biData = Request.BinaryRead(Size)
PostData = BinaryToString(biData,Size)
Response.Write "<pre>" & PostData & "</pre>" 'Verwenden Sie pre und geben Sie das Format unverändert aus
'Konvertieren Sie den Binärstrom mit Hilfe von RecordSet in Text
Funktion BinaryToString(biData,Size)
Const adLongVarChar = 201
Setze RS = CreateObject("ADODB.Recordset")
RS.Fields.Append „mBinary“, adLongVarChar, Size
RS.Öffnen
RS.AddNew
RS("mBinary").AppendChunk(biData)
RS.Update
BinaryToString = RS("mBinary").Value
RS.Schließen
Funktion beenden
%>
Der Einfachheit halber laden Sie zum Testen die einfachste Textdatei (G:homepage.txt, mit dem Inhalt „Baoyu: http://www.webuc.net “) hoch. Behalten Sie den Standardwert „default filename“ bei Dateiname im Textfeld. Senden Sie es ab und sehen Sie sich die Ausgabe an:
--------------------------------7d429871607fe
Inhaltsdisposition: form-data; name="file1"; filename="G:homepage.txt"
Inhaltstyp: Text/einfach
Baoyu: http://www.webuc.net
-------------------------7d429871607fe
Inhaltsdisposition: form-data; name="filename"
Standarddateiname
-----------------------------7d429871607fe--
Es ist ersichtlich, dass für die Elemente im Formular „----- --------------------------7d429871607fe" Solche Grenzen werden verwendet, um Teile in Teile zu unterteilen, und am Anfang jedes Teils befinden sich einige Beschreibungsinformationen , zum Beispiel: Content-Disposition: form-data; name="filename", in den Beschreibungsinformationen können Sie den Namen des Formularelements durch name="filename" ermitteln. Wenn es Inhalte wie filename="G:homepage.txt" gibt, bedeutet das, dass es sich um eine hochgeladene Datei handelt, dann enthalten die Beschreibungsinformationen eine weitere Zeile Content-Type: text/plain zur Beschreibung der Inhaltstyp der Datei. Beschreibungsinformationen und Textinformationen werden durch Zeilenumbrüche getrennt.
Nun, es ist im Grunde klar. Nach dieser Regel wissen wir, wie man die Daten trennt und verarbeitet. Ein Problem haben wir jedoch fast übersehen, nämlich den Grenzwert („-------“ oben). Beispiel) Woher wusste ---------7d429871607fe")? Dieser Grenzwert ist jedes Mal anders, wenn Sie ihn hochladen. Glücklicherweise kann er über Request.ServerVariables("HTTP_CONTENT_TYPE") in asp abgerufen werden. Im obigen Beispiel lautet der Inhalt von HTTP_CONTENT_TYPE: "multipart/form-data; border=-- --------------------------7d429871607fe“, damit können wir nicht nur feststellen, ob enctype="multipart/form- data " (Wenn es nicht verwendet wird, ist es unten nicht erforderlich, es auszuführen), Sie können auch den Grenzwert border=---------------------- erhalten ----- 7d429871607fe. (Hinweis: Der hier erhaltene Grenzwert hat am Anfang weniger „--“ als der obige Grenzwert. Es ist am besten, ihn hinzuzufügen.)
Auf den Prozess der Datenanalyse werde ich nicht näher eingehen ist nichts anderes als die Verwendung von Funktionen wie InStr und Mid, um die gewünschten Daten herauszutrennen.
2. Beim Hochladen in Blöcken sollte der Fortschrittsbalken in Echtzeit aufgezeichnet werden. Das Wesentliche ist, zu wissen, wie viele Daten der aktuelle Server in Echtzeit erhalten hat. Wenn wir an den Upload-Prozess denken, implementieren wir ihn über Request.BinaryRead(Request.TotalBytes). Während des Request-Prozesses können wir nicht wissen, wie viele Daten der aktuelle Server erhalten hat. Wir können also nur einen Workaround verwenden, wenn wir die erhaltenen Daten in Teile aufteilen und dann basierend auf der Anzahl der hochgeladenen Blöcke berechnen können, wie groß sie derzeit hochgeladen werden! Das heißt, wenn 1 KB 1 Block ist, wird der Eingabestrom zum Hochladen von 1 MB in 1024 Blöcke aufgeteilt. Wenn ich beispielsweise 100 Blöcke erhalten habe, bedeutet dies, dass 100 KB hochgeladen wurden. Als ich das Blockieren vorschlug, fanden es viele Leute unglaublich, weil sie ignorierten, dass die BinaryRead-Methode nicht nur die angegebene Größe, sondern auch kontinuierlich lesen kann.
Schreiben Sie ein Beispiel, um die Integrität des Blocklesens zu überprüfen, basierend auf dem aktuellen Beispiel (beachten Sie, dass in diesem Beispiel keine großen Dateien hochgeladen werden, da dies sonst zum Absturz des Browsers führen kann):
<%
Dimmen Sie biData, PostData, TotalBytes, ChunkBytes
ChunkBytes = 1 * 1024 ' Die Chunk-Größe beträgt 1 KB
TotalBytes = Request.TotalBytes 'Gesamtgröße
PostData = "" ' Daten in Texttyp konvertiert
ReadedBytes = 0 'Auf 0 initialisiert
„Lesen Sie in Abschnitten
Tun Sie dies, während ReadedBytes < TotalBytes
biData = Request.BinaryRead(ChunkBytes) 'Aktueller Chunk
PostData = PostData & BinaryToString(biData,ChunkBytes) 'Konvertieren Sie den aktuellen Block in Text und verbinden Sie ihn
ReadedBytes = ReadedBytes + ChunkBytes 'Lesegröße aufzeichnen
Wenn ReadedBytes > TotalBytes, dann ReadedBytes = TotalBytes
Schleife
Response.Write "<pre>" & PostData & "</pre>" ' Verwenden Sie pre und geben Sie das Format unverändert aus
' Binärstrom in Text umwandeln
Funktion BinaryToString(biData,Size)
Const adLongVarChar = 201
Setze RS = CreateObject("ADODB.Recordset")
RS.Fields.Append „mBinary“, adLongVarChar, Size
RS.Öffnen
RS.AddNew
RS("mBinary").AppendChunk(biData)
RS.Update
BinaryToString = RS("mBinary").Value
RS.Schließen
Funktion beenden
%>
Versuchen Sie gerade, die Textdatei hochzuladen. Die Ausgabeergebnisse beweisen, dass der in Blöcken gelesene Inhalt vollständig ist. In der While-Schleife können wir den aktuellen Status bei jeder Schleife aufzeichnen und dann Access übergeben Anwendung zum dynamischen Abrufen des Upload-Fortschrittsbalkens.
Außerdem: Im obigen Beispiel wird String-Splicing verwendet. Wenn Sie Binärdaten verbinden möchten, können Sie die Write-Methode des ADODB.Stream-Objekts verwenden. Der Beispielcode lautet wie folgt:
Set bSourceData = createobject("ADODB.Stream" )
bSourceData.Open
bSourceData.Type = 1 'Binär
Tun Sie dies, während ReadedBytes < TotalBytes
biData = Request.BinaryRead(ChunkBytes)
bSourceData.Write biData ' Verwenden Sie direkt die Schreibmethode, um den aktuellen Dateistream in bSourceData zu schreiben
ReadedBytes = ReadedBytes + ChunkBytes
Wenn ReadedBytes > TotalBytes, dann ReadedBytes = TotalBytes
Anwendung("ReadedBytes") = ReadedBytes
Schleife
3. Speichern Sie die hochgeladene Datei. Nach dem Trennen der hochgeladenen Datei ist die Speichermethode je nach Datentyp unterschiedlich:
Für Binärdaten können Sie den Binärstream direkt über die SaveToFile-Methode speichern ADODB.Stream-Objekt werden.
Bei Textdaten können Sie die Textdaten über die Write-Methode des TextStream-Objekts in einer Datei speichern.
Textdaten und Binärdaten können problemlos ineinander konvertiert werden. Beim Hochladen kleiner Dateien gibt es grundsätzlich keinen Unterschied zwischen beiden. Es gibt jedoch noch einige Unterschiede beim Speichern zwischen den beiden Methoden. Für das ADODB.Stream-Objekt müssen alle Daten geladen werden, bevor sie als Datei gespeichert werden können. Daher wird das Hochladen großer Dateien mit dieser Methode viel Speicher beanspruchen. und für das TextStream-Objekt: Nachdem die Datei erstellt wurde, können Sie einen Teil davon gleichzeitig und mehrmals schreiben. Dies hat den Vorteil, dass es in Kombination mit dem Prinzip des Datenabrufs nicht den Serverspeicherplatz belegt Nachdem wir die oben analysierten Blöcke analysiert haben, können wir jedes Stück hochgeladener Daten in die Dateimitte schreiben. Ich habe einmal ein Experiment durchgeführt und eine Datei mit mehr als 200 MB auf denselben Computer hochgeladen. Am Ende wurde festgestellt, dass der virtuelle Speicher des Computers nicht ausreichte Obwohl der Fortschrittsbalken anzeigt, dass die Datei hochgeladen wurde, wird die Datei am Ende immer noch nicht gespeichert. Bei letzterer Methode kommt es während des Upload-Vorgangs grundsätzlich zu keiner Speicherveränderung.
4. Ungelöste Probleme Ich habe auf dem Blog gesehen, dass Bestcomy beschreibt, dass seine Asp.Net-Upload-Komponente unabhängig von Sever.SetTimeOut sein kann, aber in Asp konnte ich das nicht. Zum Hochladen großer Dateien kann ich nur Server.SetTimeOut verwenden auf einen sehr großen Wert eingestellt werden. Ich weiß nicht, ob es eine bessere Lösung gibt.
Wenn wir beim Speichern einer Datei die Write-Methode des TextStream-Objekts verwenden, ist der hochgeladene Teil der Datei noch vorhanden, wenn der Benutzer die Dateiübertragung unterbricht. Es wäre großartig, wenn der Upload fortgesetzt werden könnte. Das Hauptproblem besteht darin, dass die Methode Request.BinaryRead zwar Blöcke einlesen kann, einen bestimmten Abschnitt des Lesens jedoch nicht überspringen kann!
5. Fazit Das Prinzip ist im Grunde klar erklärt, aber der eigentliche Code ist viel komplizierter. Es sind viele Probleme zu berücksichtigen. Der schwierigste Teil ist die Analyse der erfassten Daten Analysieren Sie, ob es sich bei dem Formularelement noch um eine hochgeladene Datei handelt und ob die Datei hochgeladen wurde ...
Ich glaube, dass Sie basierend auf der obigen Beschreibung auch Ihre eigene leistungsstarke komponentenlose Upload-Komponente entwickeln können. Ich denke, mehr Leute kümmern sich nur um den Code und wissen nicht, wie sie ihn selbst schreiben sollen. Vielleicht haben sie keine Zeit, vielleicht reicht das Niveau nicht aus und mehr davon ist einfach zur Gewohnheit geworden ... Ich habe es getan Ich habe zu viele Technologien auf CSDN gesehen. Achtteiliger Aufsatz – ein Abschnitt mit Beschreibung und dann der gesamte Code. Einem Mann das Fischen beizubringen ist nicht so gut wie ihm das Fischen beizubringen. Wenn ich Ihnen einen Code gebe, denken Sie vielleicht nicht darüber nach, warum und verwenden Sie ihn einfach. Wenn Sie das nächste Mal auf ein ähnliches Problem stoßen, wissen Sie immer noch nicht, warum. Ich hoffe, dass dieser Artikel dazu beitragen kann, dass mehr Menschen etwas lernen, und das Wichtigste ist, etwas zu „aufklären“!