Fuente: Baoyu BLOG
1. Explicaré el principio de carga sin componentes poco a poco con un ejemplo. El HTML del cliente es el siguiente. Para examinar los archivos adjuntos cargados, pasamos el elemento <input type="file">, pero asegúrese de establecer el atributo enctype del formulario en "multipart/form-data":
<form método="post" action="upload.asp" enctype="multipart/form-data">
<etiqueta>
<tipo de entrada="archivo" nombre="archivo1" />
</etiqueta>
<br />
<tipo de entrada="texto" nombre="nombre de archivo" valor="nombre de archivo predeterminado"/>
<br />
<tipo de entrada="enviar" valor="Enviar"/>
<tipo de entrada="reset" valor="Reset"/>
</formulario>
En el programa asp en segundo plano, solía ser muy fácil obtener los datos ASCII enviados por el formulario. Pero si necesita obtener el archivo cargado, debe utilizar el método BinaryRead del objeto Request para leerlo. El método BinaryRead realiza una lectura binaria de un número específico de bytes del flujo de entrada actual. Una cosa a tener en cuenta es que una vez que se usa el método BinaryRead, las colecciones Request.Form o Request.QueryString ya no se pueden usar. Combinado con la propiedad TotalBytes del objeto Solicitud, todos los datos enviados por el formulario se pueden convertir a binarios, pero todos estos datos están codificados. Primero, echemos un vistazo a cómo se codifican estos datos. ¿Hay alguna regla a seguir? En el código, convertimos el binario leído por BinaryRead en texto y lo enviamos en upload.asp en segundo plano. No cargue archivos grandes en este ejemplo; de lo contrario, el navegador podría fallar):
<%
Dim biData, PostData
Tamaño = Solicitud.TotalBytes
biData = Solicitud.BinaryRead(Tamaño)
PostData = BinaryToString(biData,Tamaño)
Response.Write "<pre>" & PostData & "</pre>" 'Utilice pre y genere el formato tal cual
'Convierte la secuencia binaria en texto con la ayuda de RecordSet
Función BinaryToString(biData,Tamaño)
Const adLongVarChar = 201
Establecer RS = CreateObject("ADODB.Recordset")
RS.Fields.Append "mBinary", adLongVarChar, Tamaño
RS.abierto
RS.AñadirNuevo
RS("mBinary").AppendChunk(biData)
RS.Actualización
BinaryToString = RS("mBinary").Valor
RS.Cerrar
Función final
%>
Para simplificar, cargue el archivo de texto más simple (G:homepage.txt, con el contenido "Baoyu: http://www.webuc.net ") para probarlo. Mantenga el valor predeterminado "nombre de archivo predeterminado" en el archivo. nombre de archivo del cuadro de texto Enviar y ver el resultado:
--------------------------------7d429871607fe.
Disposición de contenido: formulario-datos; nombre="archivo1"; nombre de archivo="G:homepage.txt"
Tipo de contenido: texto/sin formato
Baoyu: http://www.webuc.net
--------------------------7d429871607fe
Disposición de contenido: formulario-datos; nombre="nombre de archivo"
nombre de archivo predeterminado
-----------------------7d429871607fe--
Se puede ver que para los elementos del formulario, "----- --------------------------7d429871607fe" Dichos límites se utilizan para separar piezas en piezas, y hay información descriptiva al principio de cada pieza. , por ejemplo: Contenido-Disposición: formulario-datos; nombre="nombre de archivo", en la información de descripción, puede conocer el nombre del elemento del formulario a través de nombre="nombre de archivo". Si hay contenido como filename="G:homepage.txt", significa que es un archivo cargado. Si es un archivo cargado, entonces la información de descripción tendrá una línea más Tipo de contenido: texto/plain para describir. el tipo de contenido del archivo. La información de descripción y la información del cuerpo están separadas por saltos de línea.
Bueno, está básicamente claro de acuerdo con esta regla, sabemos cómo separar los datos y procesarlos. Sin embargo, casi pasamos por alto un problema, que es el valor límite ("-------" en lo anterior. ejemplo) ¿Cómo lo supo -----------------------7d429871607fe")? Este valor de límite es diferente cada vez que lo carga. Afortunadamente, se puede obtener a través de Request.ServerVariables("HTTP_CONTENT_TYPE") en asp. Por ejemplo, en el ejemplo anterior, el contenido de HTTP_CONTENT_TYPE es: "multipart/form-data; border=-- --------------------------7d429871607fe", con esto, no sólo podemos determinar si enctype="multipart/form-data "(Si no se usa, entonces no es necesario ejecutarlo a continuación), también puede obtener el valor límite de límite =---------------------- ----- 7d429871607fe. (Nota: el valor límite obtenido aquí tiene menos "--" al principio que el valor límite anterior. Es mejor agregarlo).
En cuanto al proceso de cómo analizar los datos, no entraré en detalles. No es más que usar funciones como InStr y Mid para separar los datos que queremos.
2. Al cargar en fragmentos, el progreso del registro debe reflejar la barra de progreso en tiempo real. La esencia es saber cuántos datos ha obtenido el servidor actual en tiempo real. Pensando en el proceso de carga, lo implementamos a través de Request.BinaryRead (Request.TotalBytes). Durante el proceso de solicitud, no podemos saber cuántos datos ha obtenido el servidor actual. Por lo tanto, solo podemos usar una solución alternativa si podemos dividir los datos obtenidos en partes y luego, según la cantidad de bloques que se han cargado, podemos calcular el tamaño que tienen actualmente. Es decir, si 1K es 1 bloque, entonces el flujo de entrada de carga de 1 MB se dividirá en 1024 bloques para obtener. Por ejemplo, si obtuve 100 bloques, significa que se han cargado 100K. Cuando propuse bloquear, muchas personas lo encontraron increíble porque ignoraron que el método BinaryRead no solo puede leer el tamaño especificado, sino también leer continuamente.
Escriba un ejemplo para verificar la integridad de la lectura del bloque, según el ejemplo anterior (tenga en cuenta que este ejemplo no carga archivos grandes; de lo contrario, el navegador puede fallar):
<%
Dim biData, PostData, TotalBytes, ChunkBytes
ChunkBytes = 1 * 1024 ' El tamaño del fragmento es 1K
TotalBytes = Solicitud.TotalBytes 'Tamaño total
PostData = "" 'Datos convertidos a tipo de texto
ReadedBytes = 0 'Inicializado a 0
'Leer en trozos
Hacer mientras ReadedBytes <TotalBytes
biData = Request.BinaryRead(ChunkBytes) 'fragmento actual
PostData = PostData & BinaryToString(biData,ChunkBytes) 'Convierte el fragmento actual en texto y lo une
ReadedBytes = ReadedBytes + ChunkBytes 'Tamaño de lectura del registro
Si ReadedBytes > TotalBytes Entonces ReadedBytes = TotalBytes
Bucle
Response.Write "<pre>" & PostData & "</pre>" ' Utilice pre y genere el formato tal cual
'Convierte flujo binario en texto
Función BinaryToString(biData,Tamaño)
Const adLongVarChar = 201
Establecer RS = CreateObject("ADODB.Recordset")
RS.Fields.Append "mBinary", adLongVarChar, Tamaño
RS.abierto
RS.AñadirNuevo
RS("mBinary").AppendChunk(biData)
RS.Actualización
BinaryToString = RS("mBinary").Valor
RS.Cerrar
Función final
%>
Intente cargar el archivo de texto ahora mismo. Los resultados de salida demuestran que el contenido leído en bloques está completo y, en el ciclo While, podemos registrar el estado actual en la Aplicación cada vez que se repite, y luego podemos pasar Acceder al. Aplicación para obtener dinámicamente la barra de progreso de carga.
Además: en el ejemplo anterior, se utiliza el empalme de cadenas. Si desea empalmar datos binarios, puede utilizar el método Write del objeto ADODB.Stream. El código de muestra es el siguiente:
Set bSourceData = createobject("ADODB.Stream" )
bSourceData.Open
bSourceData.Type = 1 'Binario
Hacer mientras ReadedBytes <TotalBytes
biData = Solicitud.BinaryRead(ChunkBytes)
bSourceData.Write biData 'Utiliza directamente el método de escritura para escribir la secuencia del archivo actual en bSourceData
Bytes leídos = Bytes leídos + Bytes fragmentados
Si ReadedBytes > TotalBytes Entonces ReadedBytes = TotalBytes
Aplicación("ReadedBytes") = ReadedBytes
Bucle
3. Guarde el archivo cargado. Obtenga los datos enviados a través de Request.BinaryRead. Después de separar el archivo cargado, el método de guardado es diferente según el tipo de datos:
para datos binarios, puede guardar el flujo binario directamente a través del método SaveToFile. Objeto ADODB.Stream. Conviértete en un archivo.
Para datos de texto, puede guardar los datos de texto en un archivo mediante el método Write del objeto TextStream.
Los datos de texto y los datos binarios se pueden convertir fácilmente entre sí. Para cargar archivos pequeños, básicamente no hay diferencia entre los dos. Sin embargo, todavía existen algunas diferencias al guardar entre los dos métodos. Para el objeto ADODB.Stream, todos los datos deben cargarse antes de poder guardarse como un archivo. Por lo tanto, cargar archivos grandes con este método ocupará mucha memoria. y para el objeto TextStream, una vez creado el archivo, puede escribir parte de él a la vez y escribirlo varias veces. La ventaja de esto es que no ocupará el espacio de la memoria del servidor. bloques analizados anteriormente, podemos escribir cada pieza de datos cargados en el archivo. Una vez hice un experimento y cargué un archivo de más de 200 MB en la misma máquina. Usando el primer método, la memoria siguió aumentando. Al final, indicó directamente que la memoria virtual de la computadora era insuficiente. Aunque la barra de progreso indica que el archivo se ha subido, al final el archivo aún no se guarda. Con el último método, básicamente no hay cambios en la memoria durante el proceso de carga.
4. Problemas sin resolver Vi a Bestcomy en el blog describiendo que su componente de carga Asp.Net puede ser independiente de Sever.SetTimeOut, pero en Asp no pude hacerlo. Para cargar archivos grandes, solo puedo usar Server.SetTimeOut. establecerse en un valor muy grande. No sé si hay una solución mejor.
Si utilizamos el método Write del objeto TextStream al guardar un archivo, si el usuario interrumpe la transferencia del archivo al cargarlo, la parte del archivo que se ha cargado todavía estará allí. Sería fantástico si se pudiera reanudar la carga. El problema clave es que, aunque el método Request.BinaryRead puede leer en bloques, ¡no puede saltarse una determinada sección de lectura!
5. Conclusión El principio se explica básicamente con claridad, pero el código real es mucho más complicado que esto. Hay muchas cuestiones a considerar. La parte más problemática es el análisis de los datos. Analice si pertenece a la información de descripción. El elemento del formulario todavía es un archivo cargado y si el archivo se ha cargado...
Creo que, según la descripción anterior, también puede desarrollar su propio componente de carga potente sin componentes. Creo que a más personas solo les importa el código y no saben cómo escribirlo ellos mismos. Tal vez no tengan el tiempo, tal vez el nivel no sea suficiente y más se ha convertido en un hábito... Yo sí. He visto demasiadas tecnologías en CSDN. Ensayo de ocho partes: un párrafo de descripción y luego todo el código. Enseñar a un hombre a pescar no es tan bueno como enseñarle a pescar. Si te doy un código, es posible que no pienses en por qué y simplemente lo utilices. La próxima vez que te encuentres con un problema similar, todavía no sabrás por qué. Espero que este artículo pueda ayudar a que más personas aprendan algo, ¡y lo más importante es "iluminar" algo!