Tres soluciones para la carpeta de carga B / S

Resuma los problemas de la carga de fragmentos de archivos grandes y la reanudación del punto de interrupción. Debido a que el archivo es demasiado grande (como más de 1G), debe considerar la interrupción de la red durante el proceso de carga. La solicitud de red HTTP en sí ya tiene una función de carga de fragmentos. Cuando el archivo transmitido es relativamente grande, el protocolo HTTP dividirá automáticamente el archivo (bloque), pero este no es el enfoque del que estamos hablando ahora. Lo que debemos hacer es Asegúrese de que la parte del archivo 1G que se ha cargado después de la interrupción de la red no necesita ser retransmitida la próxima vez que se conecte la red. Por lo tanto, al cargar localmente, debemos dividir el archivo grande en partes, como 1024 * 1024B, es decir, dividir el archivo grande en partes de 1M para cargarlo. Después de que el servidor lo reciba, estas partes se fusionarán en el archivo original. El principio básico La reanudación del punto de interrupción requiere que el local registre el estado de cada pieza de carga. Lo marqué a través de tres estados (espera de finalización de carga). Cuando se interrumpe la red, cargaré desde el punto de interrupción después de conectar nuevamente. El servidor juzga si el archivo ha sido cargado completamente por el nombre del archivo y el número total de piezas.

        Los detalles son los siguientes:

  1. Primero obtenga los archivos (audio, video, imágenes)

Hay dos casos, uno para obtenerlo directamente en la biblioteca del álbum y el otro para llamar a la cámara. Si se obtiene a través de UIImagePickerView (los detalles no están detallados, muchos en línea), descubriremos que cuando selecciona un video, aparecerá la página comprimida de la Figura 1, y finalmente el video obtenido por nuestra aplicación está comprimido. Video (no es el video original en la biblioteca de videos, hay una nota aquí, recuerde liberar después de operar el video comprimido, el sistema no lo liberará por usted, debe operarlo manualmente, como se describirá a continuación), y luego a través del UIImagePickerView - ( Void ) imagePickerController :( UIImagePickerController  *) selector didFinishPickingMediaWithInfo :( NSDictionary  *) información en el método de protocolo

fileInfo = {

    UIImagePickerControllerMediaType = "public.movie";

    UIImagePickerControllerMediaURL = "archivo: ///private/var/mobile/Containers/Data/Application/2AAE9E44-0E6D-4499-9AC3-93D44D8342EA/tmp/trim.F36EC46C-4219-43C8-96A7-FA7141AB64D2.8

    UIImagePickerControllerReferenceURL = "assets-library: //asset/asset.MOV? Id = DEDA9406-3223-4F87-ABB2-98FB5F5EB9C4 & ext = MOV";

}

UIImagePickerControllerMediaType es el tipo de archivo seleccionado, como KUTTypeImage, KUTTypeMovie. Tenga en cuenta aquí la diferencia entre película y video, uno es un archivo de video con sonido, uno es un archivo de video sin sonido y, por supuesto, el audio es solo sonido sin video. UIImagePickerControllerMediaURL es la URL del video (si fue tomada por la cámara, entonces este es el video original capturado; si se selecciona en la biblioteca del álbum, es el video generado después de la compresión), tenga en cuenta que esta URL no apunta a la biblioteca del álbum, a través de esta URL Puede manipular este video como eliminar, copiar, etc., puede obtener el tamaño del video comprimido. UIImagePickerControllerReferenceURL es una URL que apunta al álbum. La explicación oficial es una NSURL que hace referencia a un activo en el marco AssetsLibrary. A través de esta URL, puede obtener toda la información del video, incluido el nombre del archivo, la miniatura, la duración, etc. (a través de assetsLibrary en ALAssetsLibrary assetForURL : referenceURL resultBlock :).

Si una cámara, prestar atención a dos de almacenamiento: Guardar las imágenes del álbum assetsLibrary writeImageDataToSavedPhotosAlbum : UIImageJPEGRepresentation ([info valueForKey : UIImagePickerControllerOriginalImage], (CGFloat) 1.0 ) del Metadatos : nil completionBlock : failureBlock:

Método de compresión de alta fidelidad NSData * UIImageJPEGRepresentation (imagen UIImage *, CGFloat compressQuality)

Guarde el video en el álbum: assetsLibrary  writeVideoAtPathToSavedPhotosAlbum: MediaURL completeBlock: failureBlock:

 

Aquí, hemos obtenido todos los archivos necesarios y la información del archivo. Lo siguiente que debe hacer es dividir el archivo.

 

2. Fragmente el archivo obtenido

Primero, guardo el archivo obtenido en esa clase

@interface CNFile:  NSObject

@property  (no atómico , copia ) NSString * fileType ; // imagen o película

la @Property  ( no atómica , Copiar ) NSString * rutaArchivo; // archivo de la aplicación camino

la @Property  ( no atómica , Copiar ) NSString * nomArchivo; // nombre de archivo

la @Property  ( no atómica , ASIGNAR ) NSInteger  fileSize; // Tamaño del archivo

@property (no atómico, asignar)  NSInteger  trunks; // Número total de piezas

@property  (no atómico , copia ) NSString * fileInfo;

la @Property  ( no atómica , fuerte ) UIImage * fileImage; // miniaturas de archivos

@Property  ( no atómica , fuerte ) NSMutableArray * fileArr; // estado de la etiqueta de carga de cada pieza de

@fin

Para que podamos operar en cada objeto CNFile.

 

- ( nulo ) readDataWithChunk :( NSInteger ) archivo de fragmento :( CNFile *) archivo {

  Cómo obtener el número total de piezas:

    int  offset = 1024 * 1024 ; (el tamaño de cada segmento es 1M)

    NSInteger  chunks = (file. FileSize % 1024 == 0 )? (( Int ) (file. FileSize / 1024 * 1024 )): (( int ) (file. FileSize / ( 1024 * 1024 ) +  1 ));

    NSLog (@ "fragmentos =% ld", fragmentos ( largos ));

    Divide el archivo y lee los datos de cada pieza:

    Datos NSData *;

    NSFileHandle  * readHandle = [ NSFileHandle  fileHandleForReadingAtPath: archivo. filePath ];

    [readHandle  seekToFileOffset : offset * chunk];

    data = [readHandle  readDataOfLength : offset];

}

 

De esta manera, obtenemos los datos que se cargarán para cada pieza, y luego preguntamos al servidor si la pieza ya existe

(方法 - ( nulo ) ifHaveData :( NSData *) datos WithChunk :( NSInteger ) archivo de fragmento :( CNFile *) archivo)

Si existe, haga un fragmento + 1 y repita el método anterior para leer la siguiente pieza hasta que el servidor no exista, luego cargue la pieza de datos. En este método, preste atención para establecer el estado de carga del fragmento (espere a que finalice la carga), que estará relacionado con el juicio local de si el archivo se ha cargado por completo.

 

El siguiente paso es el proceso de carga:

- ( nulo ) uploadData :( NSData *) datos WithChunk :( NSInteger ) archivo de fragmento :( CNFile *) archivo ;

Después de que el servidor devuelve que la pieza se ha cargado correctamente, tenemos muchas cosas que hacer:

1) Primero configure la bandera de la película que se ha cargado correctamente para finalizar

[expediente. fileArr  replaceObjectAtIndex: fragmento conObjeto: @ "terminar" ];

 

2) para ver si todas las piezas de la bandera se han colocado acabado, si ya se finishi, que indica que el archivo de carga está completa, a continuación, eliminar el archivo, cargar un archivo o al final de la siguiente.

for  ( NSInteger  j = 0 ; j <fragmentos; j ++) {

if  (j == chunks || ((j == chunks - 1 ) && ([file. fileArr [j] isEqualToString : @ "finish" ])))

     [me  deleteFile : archivo. filePath ];

     [me  readNextFile ];

}

3) Si no todos terminan, verifique si la bandera utilizada por el siguiente fragmento es esperar

 NSLog (@ " Verificar el estado de la primera pieza % ld ", fragmento + 1 );

 para ( NSInteger  i = fragmento + 1 ; i <fragmentos; i ++)

  {

     NSString * flag = [archivo. fileArr objectAtIndex : i];

      if  ([flag isEqualToString : @ "wait" ]) {

             [me  readDataWithChunk : i fileName : fileName file : file];

               romper ;

          }

   }

Puede haber un 2.5 entre los pasos 2 y 3) para determinar si se suspende la carga

if (me.isPause == YES )

  {

  // Guarde la primera parte de los pocos archivos actualmente leídos en el local

     [ self  saveProgressWithChunk: chunk file: file];

      volver  ;

   }

Esta operación es en realidad lo mismo que interrumpir la red durante el proceso de carga. Para reanudar la descarga en un punto de interrupción, necesitamos guardar el progreso actual cuando la red está desconectada o pausada, para que podamos omitir la pieza anterior de finalización en la próxima carga.

Entonces hay un problema: si cargamos una pieza a la vez de forma lineal, el significado de la carga por partes se pierde realmente. Deberíamos combinar varios subprocesos para hacer que el proceso de carga por partes se ejecute simultáneamente y cargar varias piezas al mismo tiempo, lo que aumenta la eficiencia de carga. Y aproveche al máximo el ancho de banda de la red.

    dispatch_async (dispatch_queue_t queue, ^ {

        [me  readDataWithChunk : fragmento];

    })

Finalmente, preste atención a eso, después de cargar un video, vaya a la configuración para ver si el espacio de almacenamiento ocupado por su aplicación ha aumentado. Si no maneja el video comprimido generado, verá que su aplicación ocupa mucho espacio Grande

Consulte este artículo para obtener más detalles: http://blog.ncmem.com/wordpress/2019/08/12/%e5%a4%a7%e6%96%87%e4%bb%b6%e6%96%ad%e7 % 82% b9% e7% bb% ad% e4% bc% a0-2 / 
Bienvenido al grupo para discutir juntos: 374992201

Supongo que te gusta

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