Solución de carga de archivos grandes de JavaScript

Aquí solo se escribe el código de fondo. La idea básica es que el frontend fragmentará el archivo, y luego, cada vez que acceda a la interfaz de carga, pasará los parámetros al backend: el número actual de archivos y el número total de fragmentos.

Peguemos el código directamente debajo. La mayoría de los difíciles se comentan:

Subir clase de entidad de archivo:

Se puede ver que ya hay muchas funciones que necesitamos en la clase de entidad, así como atributos prácticos. Tal como la información transmitida en segundos MD5.

clase pública FileInf {

 

     public FileInf () {}

     ID de cadena pública = "";

     public String pid = "";

    public String pidRoot = "";   

     / ** * Indica si el elemento actual es un elemento de carpeta. * /

     public boolean fdTask = false;        

     // /// ¿Es un subarchivo en la carpeta /// </ summary>

     public boolean fdChild = false;

     / ** * ID de usuario. Integrarse con sistemas de terceros. * /

     public int uid = 0;

     / ** * El nombre del archivo en la computadora local * /

     public String nameLoc = "";

     / ** * El nombre del archivo en el servidor. * /

     public String nameSvr = "";

     / ** * La ruta completa del archivo en la computadora local. Ejemplo: D: \ Soft \ QQ2012.exe * /

     public String pathLoc = "";  

     / ** * La ruta completa del archivo en el servidor. Ejemplo: F: \\ ftp \\ uer \\ md5.exe * /

     public String pathSvr = "";

     / ** * La ruta relativa del archivo en el servidor. Ejemplo: /www/web/upload/md5.exe * /

     public String pathRel = "";

     / ** * Archivo MD5 * /

     Cadena pública md5 = "";

     / ** * Longitud del archivo digitalizado. En bytes, ejemplo: 120125 * /

     public long lenLoc = 0;

     / ** * Tamaño de archivo formateado. Ejemplo: 10.03MB * /

     cadena pública sizeLoc = "";

     / ** * Ubicación de la reanudación del archivo. * /

     desplazamiento largo público = 0;

     / ** * Tamaño subido. En bytes * /

     public long lenSvr = 0;

     / ** * Porcentaje cargado. Ejemplo: 10% * /

     public String perSvr = "0%";

     public boolean complete = false;

     public Date PostedTime = new Date ();

     público booleano eliminado = falso;

     / ** * Ya sea que se haya escaneado o no, se proporciona para su uso en carpetas grandes y el escaneo comienza después de cargar las carpetas grandes. * /

     público booleano escaneado = falso;

}

 

El primero es la lógica de recepción de datos del archivo, que es responsable de recibir los datos del bloque de archivos cargados por el control y luego escribirlos en el archivo del servidor. El control ha proporcionado la información de índice, tamaño, MD5 y longitud del bloque. Podemos manejarlo de manera flexible según nuestras necesidades, y también podemos guardar los datos del bloque de archivos en el sistema de almacenamiento distribuido.

<%

out.clear ();

Cadena uid = request.getHeader ("uid"); //

Cadena id = request.getHeader ("id");

Cadena lenSvr = request.getHeader ("lenSvr");

Cadena lenLoc = request.getHeader ("lenLoc");

Cadena blockOffset = request.getHeader ("blockOffset");

Cadena blockSize = request.getHeader ("blockSize");

Cadena blockIndex = request.getHeader ("blockIndex");

Cadena blockMd5 = request.getHeader ("blockMd5");

Cadena completa = request.getHeader ("completa");

String pathSvr = "";

 

// El parámetro está vacío.

if (StringUtils.isBlank (uid)

     || StringUtils.isBlank (id)

     || StringUtils.isBlank (blockOffset))

{

     XDebug.Output ("el parámetro es nulo");

     regreso;

}

 

// Comprueba que tenemos una solicitud de carga de archivos

boolean isMultipart = ServletFileUpload.isMultipartContent (solicitud);

FileItemFactory factory = new DiskFileItemFactory ();  

ServletFileUpload upload = nuevo ServletFileUpload (fábrica);

Lista de archivos = nulo;

tratar

{

     archivos = upload.parseRequest (solicitud);

}

catch (FileUploadException e)

{// Error al analizar los datos del archivo 

    out.println ("error de lectura de datos de archivo:" + e.toString ());

    regreso;

  

}

 

FileItem rangeFile = null;

// Obtenga todos los archivos cargados

Iterator fileItr = files.iterator ();

// Recorrer todos los archivos

while (fileItr.hasNext ())

{

     // obtener el archivo actual

     rangeFile = (FileItem) fileItr.next ();

     if (StringUtils.equals (rangeFile.getFieldName (), "pathSvr"))

     {

         pathSvr = rangeFile.getString ();

         pathSvr = PathTool.url_decode (pathSvr);

     }

}

 

verificación booleana = falso;

Cadena msg = "";

String md5Svr = "";

long blockSizeSvr = rangeFile.getSize ();

if (! StringUtils.isBlank (blockMd5))

{

     md5Svr = Md5Tool.fileToMD5 (rangeFile.getInputStream ());

}

 

verificar = Integer.parseInt (blockSize) == blockSizeSvr;

si (! verificar)

{

     msg = "error de tamaño de bloque sizeSvr:" + blockSizeSvr + "sizeLoc:" + blockSize;

}

 

if (verifique &&! StringUtils.isBlank (blockMd5))

{

     verificar = md5Svr.equals (blockMd5);

     si (! verifique) msg ​​= "error de bloque md5";

}

 

si (verificar)

{

     // Guardar datos de bloque de archivo

     FileBlockWriter res = new FileBlockWriter ();

     // Solo se crea el primer bloque

     if (Integer.parseInt (blockIndex) == 1) res.CreateFile (pathSvr, Long.parseLong (lenLoc));

     res.write (Long.parseLong (blockOffset), pathSvr, rangeFile);

     up6_biz_event.file_post_block (id, Integer.parseInt (blockIndex));

    

     JSONObject o = new JSONObject ();

     o.put ("mensaje", "ok");

     o.put ("md5", md5Svr); 

     o.put ("offset", blockOffset); // Posición de desplazamiento de bloque basada en archivo

     msg = o.toString ();

}

rangeFile.delete ();

out.write (mensaje);

%>

 

Sección de inicialización de archivo

<%

out.clear ();

WebBase web = nueva WebBase (pageContext);

Id. De cadena = web.queryString ("id");

Cadena md5 = web.queryString ("md5");

String uid = web.queryString ("uid");

String lenLoc = web.queryString ("lenLoc"); // El tamaño del archivo digitalizado. 12021

String sizeLoc = web.queryString ("sizeLoc"); // El tamaño del archivo formateado. 10MB

Devolución de llamada de cadena = web.queryString ("devolución de llamada");

Cadena pathLoc = web.queryString ("pathLoc");

pathLoc = PathTool.url_decode (pathLoc);

 

// El parámetro está vacío.

if (StringUtils.isBlank (md5)

     && StringUtils.isBlank (uid)

     && StringUtils.isBlank (sizeLoc))

{

     out.write (devolución de llamada + "({\" valor \ ": nulo})");

     regreso;

}

 

FileInf fileSvr = nuevo FileInf ();

fileSvr.id = id;

fileSvr.fdChild = false;

fileSvr.uid = Integer.parseInt (uid);

fileSvr.nameLoc = PathTool.getName (pathLoc);

fileSvr.pathLoc = pathLoc;

fileSvr.lenLoc = Long.parseLong (lenLoc);

fileSvr.sizeLoc = sizeLoc;

fileSvr.deleted = false;

fileSvr.md5 = md5;

fileSvr.nameSvr = fileSvr.nameLoc;

 

// Todos los archivos individuales se almacenan en uuid / file

PathBuilderUuid pb = new PathBuilderUuid ();

fileSvr.pathSvr = pb.genFile (fileSvr.uid, fileSvr);

fileSvr.pathSvr = fileSvr.pathSvr.replace ("\\", "/");

 

DBConfig cfg = new DBConfig ();

DBFile db = cfg.db ();

FileInf fileExist = new FileInf ();

    

boolean exist = db.exist_file (md5, fileExist);

// El mismo archivo ya existe en la base de datos, y hay progreso de carga, luego use esta información directamente

if (existe && fileExist.lenSvr> 1)

{

     fileSvr.nameSvr = fileExist.nameSvr;

     fileSvr.pathSvr = fileExist.pathSvr;

     fileSvr.perSvr = fileExist.perSvr;

     fileSvr.lenSvr = fileExist.lenSvr;

     fileSvr.complete = fileExist.complete;

     db.Add (fileSvr);

    

     // Evento desencadenante

    up6_biz_event.file_create_same (fileSvr);

} // Este archivo no existe

más

{

     db.Add (fileSvr);

     // Evento desencadenante

    up6_biz_event.file_create (fileSvr);

    

     FileBlockWriter fr = nuevo FileBlockWriter ();

     fr.CreateFile (fileSvr.pathSvr, fileSvr.lenLoc);

}

 

Gson gson = nuevo Gson ();

Cadena json = gson.toJson (fileSvr);

 

json = URLEncoder.encode (json, "UTF-8"); // Codificación, para evitar confusiones chinas

json = json.replace ("+", "% 20");

json = devolución de llamada + "({\" valor \ ": \" "+ json +" \ "})"; // devuelve datos en formato jsonp.

out.write (json);%>

 

El primer paso: obtener RandomAccessFile, objeto de clase de archivo de acceso aleatorio

El segundo paso: llame al método getChannel () de RandomAccessFile para abrir el canal de archivos FileChannel. Esta lógica se puede optimizar. Si hay una necesidad de almacenamiento distribuido en el futuro, se puede cambiar a almacenamiento distribuido para reducir la presión en un solo servidor.

clase pública FileBlockWriter {  

     public FileBlockWriter () {} 

     public void CreateFile (String pathSvr, long lenLoc)

     {

         tratar

         {

              Archivo ps = nuevo archivo (pathSvr);

              PathTool.createDirectory (ps.getParent ());

             

             RandomAccessFile raf = new RandomAccessFile (pathSvr, "rw");

             raf.setLength (lenLoc); // corrección: crea el archivo en su tamaño original

             raf.close ();

 

         } catch (IOException e) {

              // TODO Bloque de captura generado automáticamente

              e.printStackTrace ();

         }       

     }

    

     escritura pública vacía (desplazamiento largo, String pathSvr, bloque FileItem)

     {       

         tratar

         {

              InputStream stream = block.getInputStream ();           

              byte [] datos = nuevo byte [(int) block.getSize ()];

              stream.read (datos);

              stream.close ();            

             

              RandomAccessFile raf = new RandomAccessFile (pathSvr, "rw");

              raf.seek (desplazamiento);

              raf.write (datos);

              raf.close ();

             

         } catch (IOException e) {

              // TODO Bloque de captura generado automáticamente

              e.printStackTrace ();

         }

     }

}

Paso 3: Obtenga el número actual de bloques y calcule el último desplazamiento del archivo

Paso 4: Obtenga la matriz de bytes del bloque de archivos actual, que se utiliza para obtener la longitud de bytes del archivo

Paso 5: Use el método map () del File File de la clase FileChannel para crear un buffer de byte directo MappedByteBuffer

Paso 6: Coloque la matriz de bytes de bloque en el búfer en la posición actual mappedByteBuffer.put (byte [] b);

Paso 7: Libere el búfer

Paso 8: compruebe si el archivo está completamente cargado

 

Escaneo de carpetas

 

 

Clase de generación de ruta de almacenamiento

 

Bueno, esto se acabó. Si tiene alguna pregunta o crítica, los comentarios y mensajes privados son bienvenidos. Vamos a crecer juntos y aprender juntos.

Finalmente, pon una imagen de efecto

 

La lógica del código de fondo es casi la misma, y ​​actualmente es compatible con MySQL, Oracle, SQL. Antes de usar, debe configurar la base de datos, puede consultar este artículo que escribí: http://blog.ncmem.com/wordpress/2019/08/07/java carga y descarga de archivos enormes /

Bienvenido a unirse al grupo para discutir: 374992201

Supongo que te gusta

Origin www.cnblogs.com/songsu/p/12704752.html
Recomendado
Clasificación