Divide y vencerás, carga archivos grandes en partes

Aquí estamos involucrados en un algoritmo - algoritmo de ramificación

En el proyecto de plataforma de publicidad que comencé recientemente, debido a que se requiere que el cliente proporcione un video autocertificado, prueba la autenticidad de mi empresa.

Hoy en día, la resolución del video es cada vez más alta, lo que a menudo va acompañado de una enorme memoria de video. Un video de unos pocos minutos necesita varios gigabytes de memoria. Definitivamente no es posible usar métodos de carga ordinarios. El archivo es grande y la velocidad es lenta, lo que afecta la experiencia del cliente. Para resolver este problema, adopté el método de cargar en partes, dividiendo un archivo grande en n archivos pequeños para cargar, ¡para acelerar la eficiencia de transmisión!

Aquí estamos involucrados en un algoritmo - algoritmo de ramificación

El concepto de carga fragmentada es el algoritmo divide y vencerás, divide y vencerás, transforma un gran problema en múltiples problemas pequeños y ¡resuélvelos! !

Fragmentación frontal

En primer lugar, hacemos la fragmentación en el front-end, y la fragmentación se transmite al back-end. Aquí uso vue3, el marco de interfaz de usuario es ant-desgin y el control utilizado es a-upload. El usuario hace clic en cargar para seleccionar el archivo a cargar.

En este momento, podemos obtener el nombre y el tamaño del archivo, y luego definir el tamaño del fragmento que desea. Aquí puede escribir un juicio, decirle el tamaño del archivo que desea cargar y definir el tamaño de tu fragmento Si el archivo es demasiado pequeño, simplemente No hay necesidad de fragmentación, lo que consume recursos. En este momento, podemos obtener el número total de piezas, porque habrá un resto, así que uso el método Math.ceil de redondeo para obtener el número total de piezas. En este momento, podemos obtener la posición de inicio y la posición final de cada segmento, y luego dividir el archivo en segmentos y enviarlo al backend para su procesamiento.

//上传方法
    handleChange:function(file){

      //获取文件大小    1024字节   1kb
      console.log(file.file)
      
      var size = file.file.size
      this.size = size
      // this.filename = file.file.name

      //定义分片大小
      var shardSize = 1024 * 100

      //总片数
      //向上取整
      this.shardCount = Math.ceil(size / shardSize)

      //切片操作
      for (var i=0;i<this.shardCount; ++i){
        //开始位置
        var start = i * shardSize

        //结束位置
        var end = Math.min(size,start+shardSize)

        //切片
        var shardfile = file.file.slice(start,end)

        this.pushshard(shardfile,file.file.name,i)
      }
      


    },

¡Hasta ahora, la lógica de fragmentación frontal está completa!


Backend escribe de forma asíncrona

Utilizo el marco tronado en python para escribir de forma asincrónica en el back-end. Para evitar el bloqueo causado por la escritura sincrónica, instale la biblioteca aiofiles y coopere con el mecanismo asincrónico de tornado para mejorar la eficiencia de la escritura.

Aquí, el backend obtiene la entidad del archivo, el nombre del archivo y el indicador, primero escribe la entidad del archivo en la ruta especificada de forma asíncrona, luego la lee y la fusiona en orden. están todos arreglados Gramática, no hay lógica, se muestra el siguiente código, mírelo usted mismo

# 分片上传
class SliceUploadHandler(BaseHandler):
    #合并分片
    async def put(self):
        filename = self.get_argument("filename",None)
        count = 0
        size = self.get_argument("size",None)

        try:
            filesize = os.path.getsize("./static/upload/{}".format(filename))
        except Exception as e:
            print(str(e))
            filesize = 0

        if int(size) != filesize:

            #异步打开文件句柄
            async with aiofiles.open("./static/upload/{}".format(filename),"ab") as file:
                while True:
                    try:
                        #读取分片
                        shard_file = open("./static/upload/{}_{}".format(filename,count),"rb")
                        #异步写入
                        await file.write(shard_file.read())
                        #手动关闭句柄
                        shard_file.close()

                    except Exception as e:

                        print(str(e))

                        break

                    count = count + 1

                self.finish({"errcode":0,"msg":"合并完毕"})


    # 分片文件接收
    async def post(self):
        #接收分片实体
        file = self.request.files["file"][0]

        #获取下标
        count = self.get_argument("count",None)

        #获取文件名
        filename = self.get_argument("filename",None)


        #获取文件内容
        content = file["body"]

        #异步写入
        async with aiofiles.open("./static/upload/{}_{}".format(filename,count),"wb") as file:

            #异步
            await file.write(content)

        self.finish({"errcode":0,"msg":"分片上传成功"})

Hasta ahora, el backend ha sido depurado. Además, en el escenario real de transferencia de archivos grandes, debido a la red u otros factores, la tarea de fragmentación puede interrumpirse. En este momento, es necesario responder rápidamente degradando y devolviendo el Para evitar largas esperas a los usuarios, aquí usamos la biblioteca Apscheduler basada en Tornado para programar tareas de fragmentación.

Supongo que te gusta

Origin blog.csdn.net/qwertyu111j/article/details/126038796
Recomendado
Clasificación