1. Visão geral do curso
No desenvolvimento do sistema de aplicativos da Web, a função de upload de arquivos é uma função muito comum. Hoje, vamos falar principalmente sobre a implementação técnica relevante da função de upload de arquivos no Javaweb. Com o rápido desenvolvimento da tecnologia da Internet, os requisitos de experiência dos usuários para sites estão cada vez mais altos. Também existem muitos pontos inovadores na tecnologia da função de upload de arquivos, como upload assíncrono, upload de arrastar e arrastar, fazer o upload de colar, fazer upload de monitoramento de progresso, miniaturas de arquivo, transmissão contínua de ponto de interrupção de grandes arquivos, transmissão instantânea de arquivo grande, etc.
Noções básicas necessárias para este curso:
Entenda o conteúdo básico do protocolo HTTP
Tecnologia básica de operação de fluxo de IO
Noções básicas do servlet
Conhecimento básico da tecnologia JavaScript/JQuery
2. Noções básicas de upload de arquivo
Para upload de arquivo, o navegador envia o arquivo para o lado do servidor na forma de um fluxo durante o processo de upload e todos os dados de streaming serão transportados para o lado do servidor com a solicitação HTTP. Portanto, o formato do conteúdo solicitado ao fazer o upload do arquivo deve ser basicamente entendido.
Página de upload de arquivos:
<Form Action = "/ItheimaUplOad/uploadServlet" Method = "Post" ENCTYPE = "Multipart/Form-Data"> Por favor, selecione o arquivo carregado: <input type = "file" name = "Anex"/> <br/> <input Type = "submit" value = "submit"/> </formulário>
Conteúdo da solicitação HTTP:
3. Java Background usa servlet para receber arquivos
É problemático se você usar o Servlet para obter o fluxo de entrada de arquivos carregados e analisar os parâmetros de solicitação nele. Portanto, de um modo geral, o plano de fundo escolhe usar o componente de upload de arquivo-fil-FileUpload, a ferramenta de código aberto do Apache.
// Código de fundo java: upload de componentes do Commons-FileUpload File Public Class UploadServlet estende httpServlet {public void Doget (httpServletReQuest Solicy, httpServletResponse) lança servleTexception, ioexception {// 1. Configure o cache DiskFileItemFactory Factory = new DiskFileItemFactory (1*1024*1024, novo arquivo ("c:/tempfiles/")); // 2. Crie servLeFileUpload Object ServletFileUpload sfu = new ServletFileUpload (fábrica); // Resolva o problema chinês do nome do arquivo sfu.setheadeRencoding ("UTF-8"); // 3. Resolve Try {List <FileItem> list = sfu.parserequest (request); // Resolva todo o conteúdo se (list! = Null) {for (fileItem item: list) {// determinar se é um parâmetro de formulário normal; value = item.getString ("UTF-8"); } else {// arquivo if (item.getName ()! = null &&! item.getName (). Equals ("")) {// Salvar no servidor FileUtils de disco rígido (FileUploadexception e) {e.printStackTrace ();}} public void DoPost (solicitação httpServletRequest, httpServletResponse resposta) lança servletexception, iooxception {doget (solicitação, resposta);}}}}}}4. Use WebPloader para fazer upload de componentes
Na extremidade frontal da página de upload de arquivo, podemos optar por usar alguns componentes de upload mais úteis, como o componente de código aberto do Baidu. Esse componente pode basicamente atender a algumas funções diárias de upload de arquivos, como upload assíncrono, upload de arrastar e soltar, colar o upload, fazer upload de monitoramento de progresso, miniaturas de arquivo e até grandes pontos de interrupção do arquivo para continuar a transmissão e a transmissão de arquivos grandes em segundos.
Baixe o componente WebUpload
http://fex.baidu.com/webuploader/ Baixe o pacote webupload no site oficial do WebUpload
Estrutura do diretório WebUpload:
Demonstração básica de upload de arquivos (incluindo o progresso do upload)
front-end
1.1 Importar o CSS, JS necessário na página
<link rel = "Stylesheet" type = "text/css" href = "$ {PageContext.Request.ContextPath} /css/webuploader.css"> <script type = "text/javascript" src = "$ {pageConetxt.request.CONT.CONT.CONTET.CONTET.CONTET.CONTET.CONTET.CONTE =" } /js/jquery-1.10.2.min.js "> </script> <script type =" text/javascript "src =" $ {PageContext.request.ContextPath} /js/webuploader.js "> </cript>1.2 Escreva a etiqueta da página de upload
<!-upload div-> <div id = "uploader"> <!-exibir informações da lista de arquivos-> <ul id = "filelist"> </ul> <!-selecione área de arquivo-> <div id = "filepicker"> clique para selecionar Arquivo </div> </div>
1.3 Escrevendo o código WebPload
<script type = "text/javascript"> // 1. Initialize webupload e configure parâmetros globais var uploader = webupLoader.create ({// endereço de controle flashk swf: "$ {PageContext.request.ContextPath} /js/uploader.swf", // Submission Serverpath: "$ {PageConxtxt.ret.rent.rent.rent.rent.rent.renting.retternConst.TeLTET.TELTENTEXTEMTENTEXTEMTENTET {PageConText.rent.rent.requt.relTert. Escolha de tags do controle: "#FilePicker", // Auto do arquivo de upload automaticamente: true,}); // 2. Após selecionar o arquivo, a fila de informações do arquivo exibe // Registre o evento FileCEUed: acionado quando o arquivo é adicionado à fila // File: Representa o uploader de arquivo atualmente selecionado.on ("filequeed", function (file) {// Adicionar informações sobre o arquivo Div $ ("#FILELIST"). Append ("<div Id = '" " class = 'fileInfo'> <pan> "+file.name+" </span> <div class = 'state'> aguardando o upload ... </div> <span class = 'text'> </span> </div> ");}); // 3. Registre o upload de progresso escuta // arquivo: carregando arquivo // porcentagem: a proporção do progresso atual. O máximo é 1. Por exemplo: 0.2UPLOADER.ON ("UPLOUPPROGRESS", function (arquivo, porcentagem) {var id = $ ("#"+file.id); // Atualizar informações de informações de status. id.find ("span.text"). text (math.ound (porcentagem*100)+"%");}); // 4. Registre e usear o arquivo // Arquivo: Arquivo carregado // Resposta: Dados retornados pelo plano de fundo, retorne uploader.on ("uploadSuccess", function (arquivo, resposta) {// Atualize informações de status $ ("#"+file.id) .find ("div.state"). Text ("upload");});2) Código de servlet de back -end
DiskFileItemFactory Factory = new DiskFileItemFactory (); ServletFileUpload sfu = new ServletFileUpload (Factory); sfu.setheadeRencoding ("Utf-8"); Try {List <FileItem> itens = Sfu.ParSereQuest (request); Informações} else {// Informações do arquivo // julga que apenas os arquivos precisam ser salvos e processados System.out.println ("Nome do arquivo recebido:"+item.getName ()); // copie o arquivo para o disco rígido no fileutil.copyInputStreamTofile (Item.getInpTream (), novo FileThPath+" com sucesso ");}}} catch (fileUploadexception e) {e.printStackTrace ();}Gerar miniaturas de imagem
Ponto -chave: Call Uploader.makethumb () Método para gerar miniaturas
uploader.on ("fileQueed", function (file) {// Anexe informações do arquivo div $ ("#fileList"). Append ("<div id = '"+file.id+"' class = 'fileInfo'> <img/> <span>"+file.name+"</span> <div clássia = 'Estado'> class = 'text'> </span> </div> "); // Faça com que as miniaturas: ligue para makethumb () // Erro: Falha ao criar miniaturas // src: caminho de miniatura uploader.makethumb (arquivo, função (erro, src) {var id = $ ("#"" +.id); se (error) {id.find ("img"). Substituir ("não pode visualizar");} // Se for bem -sucedido, a miniatura será exibida no id.find ("img"). att ("src", src);Arraste, cole e carregue
1) Adicione uma div à área de arrasto na página
<!-Upload div-> <div id = "uploader"> <!-arrasto de arrasto Área de arrastar-> <div id = "dNDarea"> <p> arrastar o arquivo diretamente aqui para fazer upload automaticamente </p> </div> <!-Exibir informações da lista de arquivos-> <ul id = "filelist"> </ul> <!-selecionar área->
2) Adicione parâmetros de arrastar e soltar aos parâmetros de configuração global do WebUploader
// 1. Initialize webupload e configure parâmetros globais var uploader = webupLoader.create ({// endereço de controle flashk swf: "$ {PageContext.request.ContextPath} /js/uploader.swf", // Submission Serverpath: "$ {PageConxtxt.ret.rent.rent.rent.rent.rent.renting.retternConst.TeLTET.TELTENTEXTEMTENTEXTEMTENTET {PageConText.rent.rent.requt.relTert. Escolha de tags do Control: "#FilePicker", // Auto do arquivo de upload automaticamente: true, // Ative a função de arrastar e soltar, especifique a área de arrasto DND: "#dNDarea", // Desative a função Drag and Shop em outros locais da página para impedir que a página abriu diretamente o arquivo desabilleglobdnd: True // Enable Paste:#uplown "Carregue arquivos grandes em pedaços
1) Adicione parâmetros de upload de bloco aos parâmetros globais do webuploader
// 1. Initialize webupload e configure parâmetros globais var uploader = webupLoader.create ({// endereço de controle flashk swf: "$ {PageContext.request.ContextPath} /js/uploader.swf", // Submission Serverpath: "$ {PageConxtxt.ret.rent.rent.rent.rent.rent.renting.retternConst.TeLTET.TELTENTEXTEMTENTEXTEMTENTET {PageConText.rent.rent.requt.relTert. control's tag pick:"#filePicker",//Auto upload file auto:true,//Enable drag and drop function, specify the drag area dnd:"#dndArea",//Disable page Drag and drop function in other places to prevent the page from opening the file directly disableGlobalDnd:true,//Enable paste function paste:"#uploader",//Set in chunked:true,//Where to upload CHUNKED: TRUE, // Tamanho do arquivo por bloco (padrão 5m) ChunkSize: 5*1024*1024, // Abra vários threads simultâneos (padrão 3) threads: 3, // Ao carregar o arquivo atual, preparenextfile: true});2) Monitore três pontos no tempo para fazer upload de arquivos
Depois de adicionar as três configurações acima, você descobrirá que, quando o arquivo exceder 5m, o WebUploader enviará automaticamente o arquivo para o segundo plano.
Cada solicitação de bloco contém informações:
Você pode ouvir três pontos de tempo importantes nos uploads de arquivos em pedaços.
Faleira antes do SIFT: Ligue antes de envio antes: se houver blocos, ligue para o arquivo após o envio antes de cada bloco ser enviado: chamado após todos os blocos forem enviados // 5. Monitore os três momentos de carregamento do arquivo (Nota: Esta seção do código deve ser colocada antes do webupLoader.create) // ponto de tempo 1 :: Antes de todos os blocos serem carregados (1. A marca exclusiva do arquivo pode ser calculada; 2 rush. Transmissão contínua de ponto de interrupção) // Etapa 3: Depois que todos os pedaços são carregados com sucesso (1. Notifique o fundo dos arquivos de pedaços para mesclar) webuploader.uploader.register ({"antes-send-file": "beforesendfile", "antes-send": "beforesend", "snd-file" ":" Suntfile "," antes de secar ":" beforesend "," send-file "": "Sentfile": "Antes de Send": "beforesend", "snd-file": " Upload em todos os chunks beforesendfi le: function () {// 1. Solicite se o plano de fundo salvou o bloco atual. Se houver, pule o arquivo de bloco para realizar a função de transmissão contínua do ponto de interrupção}, // Etapa 3: chame essa função depois que todos os blocos forem carregados com sucesso após ofile: function () {// 1. Se for enviado em blocos, todos os arquivos de bloco serão mesclados através do plano de fundo}});Lógica de arquivo anterior:
// use o método md5file () para calcular a tag exclusiva do arquivo // Esta função recebe um adiForeSesendFile: function (file) {// Crie um adiado adiado = webuploader.deferred (); // 1. Calcule a etiqueta exclusiva do arquivo, usada para transmissão contínua do ponto de interrupção e segunda transmissão (new webuploader.uploader ()). recuperado ... ");}). Então (function (val) {uncelfileTag = val; $ ("#"+file.id) .find (" div.state "). Texto (" Informações de arquivo obtidas com êxito "); // somente quando as informações do arquivo são obtidas com sucesso, a próxima operação será executada adiada.etSolve ();}; Solicite se o plano de fundo salvou o arquivo. Se existir, o arquivo será ignorado para realizar a segunda função de passagem // return adtered.promise ();}Lógica antes de ser enviada:
// Envie uma etiqueta exclusiva do arquivo atual para o plano de fundo, usado para criar um diretório que salva o arquivo em chunked beforesend: function () {// carrega a etiqueta exclusiva do arquivo atual para o plano de fundo, que é usado para criar um diretório que salva o arquivo em chunked this.owners.option.oportdata.Filemd5 = FILEM5;3) O plano de fundo precisa salvar todos os arquivos em chunked
// Crie um diretório para cada arquivo e salve todos os arquivos fundidos deste arquivo // julgue se ele foi enviado em pedaços se (chunks! = Null) {System.out.println ("Processamento de Chunk ..."); // Crie um diretório temporário para salvar todos os arquivos de arquivos Chunked; if (! chunksdir.exists ()) {chunksdir.mkdir ();} if (chunk! = null) {// salve chunkfile chunkFile = new File (chunksdir.getPath ()+"/"+chunk); fileUtils.copyununununkin);4) A recepção notifica o back -end para mesclar todos os arquivos em chunked
// A recepção notifica o plano de fundo para mesclar arquivos lógica após o arquivo: AfterSendFile: function (FILE) {// 1. Se carregado em pedaços, mescla todos os arquivos de pedaços através do plano de fundo // solicite o plano de fundo para mesclar arquivos $ .ajax ({type: "post", url: "$ {PageContext.Request.ContextPath}/uploadCheckServlet? Action = Mergechunks", Data: {// File tag Filmd5 arquivo de arquivo: file.name}, datatype: "json", sucesso: function (resposta) {alert (resposta.msg);}}});} // em segundo plano mesclado todos os arquivos se if ("startgets" .equals (ação)) {system.out.println ("start mérge dos arquivos ..."); filename = request.getParameter ("nome do arquivo"); // Leia todos os arquivos no arquivo de diretório f = novo arquivo (serverPath+"/"+filemd5); file [] FileArray = f.ListFiles (new FileFilter () {// exclui diretório, o arquivo public boolean (FILEFIME) {Pathname (Pathn) {// exclui (FILDN) {// exclui (FILDN) (FILDNATE) {// exclui, o FILDNEM. true;}}); // converte em uma coleção para facilitar a lista de classificação <File> filelist = new ArrayList <File> (Arrays.asList (FileArray)); // Classificar de Small para Large Coleções.sort (FILELIST, NOVO Comparador <File> () {public int compare (Arquivo O1, File O1) {se Integer.ParseInt (o2.getName ())) {return -1;} return 1;}}); arquivo outputfile = new File (serverPath+"/"+filename); // crie o arquivo de outputfile.CreatStream (); para (arquivo de arquivo: fileList) {Inchannel = new FileInputStream (file) .getChannel (); Inchannel.Transferto (0, Inchannel.size (), outChannel); Inchannel.Close (); if (tempfile.isdirectory () && tempfile.exists ()) {tempfile.delete ();} // feche o fluxo outchannel.close (); resposta.setContentType ("text/html; charset = utf-8"); resposta.getwriter (). com sucesso/"}");}Grandes pontos de interrupção continuam
Com base na implementação do upload de blocos, é muito simples implementar a transmissão contínua do ponto de interrupção! ! !
front-end:
// Ponto de tempo 2: se houver upload de bloco, essa função será chamada antes de cada bloco de upload //: representa o objeto de bloco atual beforesend: function (block) {// 1. Solicite se o plano de fundo salvou o bloco atual. Se existir, pule o arquivo de bloco para realizar a função de transmissão contínua do ponto de interrupção var Se tiver sido salvo, será ignorado. Caso contrário, o conteúdo do pedaço será enviado $ .ajax ({type: "post", url: "$ {pageContext.Request.ContextPath}/uploadCheckServlet? Action = checkChunk", Data: {// o arquivo exclusivo Mark Filemd5: Filemd5, // Current Chunk Subsessal Lock.end-block.start}, Datatype: "JSON", SUCCESS: function (Response) {if (Response.ifexist) {// O bloco existe, pule o bloco adiado.reject ();} else {// o bloco não existe ou é incompleto e reende o conteúdo de bloco. Antecedentes Crie o diretório que salva o arquivo bloqueia this.owner.options.formData.filemd5 = filemd5; return adtered.promise (); },Nos bastidores:
// verifique se o pedaço existe ou salva o checkChunk de void privado (solicitação httpServletRequest, httpServletResponse resposta) lança a ioexception, filenotfoundException {System.out.println ("checkChunk ..."); string filemd5 = request.getParâmetro ("FIMEMD5"); request.getParameter ("chunksize"); arquivo de verificação de arquivo = novo arquivo (serverPath+"/"+filemd5+"/"+chunk); resposta.setContentType ("text/html; charset = utf-8"); // verifique se o arquivo existe e o tamanho é consistente se (quadrofile.exts (); checkFile.Length () == Integer.ParseInt (ChunkSize)) {Response.getWriter (). Write ("{/" ifexist/": 1}");} else {Response.getWriter (). Write ("{/" ifexist/": 0});}}Transferência de arquivos em segundos
Antes de todas as solicitações de bloqueio, a segunda função de transferência pode ser implementada! ! !
front-end:
beforesendfile: function (file) {// crie um DefferedVar adiado = webUploader.deferred (); // 1. Calcule a marca exclusiva do arquivo, usada para transmissão contínua do ponto de interrupção e segunda transmissão (new webupLoader.upLoader ()). informação ... ");}). Então (function (val) {filemd5 = val; $ ("#"+file.id) .find (" div.state "). text (" informações obtidas com êxito "); // 2. Solicite se o fundo salvou o arquivo. Se ele existir, pular o arquivo para realizar a segunda função de passagem $ .ajax ({type: "post", url: "$ {pageContext.request.contextpath}/uploadcheckServlet? Action = FileCheck", dados: {// a tag exclusiva do arquivo do arquivo filemd5: filemd5}, datatype: "json", sucesso: function (resposta) {if (resposta.ifexist) {$ ("#"+file.id) .find ("div.state"). text ("transferido com sucesso"); adiado.Resolve ();}}});}); // retorna adiarten adferred.promise ();},Nos bastidores:
/Verifique se os dados do MD5 do arquivo estão relacionados ao banco de dados privado void FileCheck (solicitação httpSertLeQuest, httpServletResponse Response) lança ioexception, fileNotfoundException {string filemd5 = requestParameter ("filemd5"); // simular o mapa do dadoSt. Hashmap <string, string> (); database.put ("576018603F4091782B68B78AF85704A1", "01 Revisão.itcast "); resposta.setContentType (" text/html; charset = utf-8 "); if (database.containsKey (filemd5)) {Response.getWriter ().O acima exposto é um exemplo de explicação do upload e do download do arquivo javaweb que o editor apresentou a você (Cool Arquive Upload Technology). Espero que seja útil para todos. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a todos a tempo. Muito obrigado pelo seu apoio ao site wulin.com!