1. Visão geral do upload de arquivo
Para realizar a função de upload de arquivos no desenvolvimento da Web, são necessárias duas etapas:
1. Adicione itens de entrada de carregamento na página da web
<form action = "#" method = "post" Enctype = "Multipart/form-Data"> <input type = "file" name = "filename1"/> <br> <input type = "file" name = "filename2"/> <br> <bring typ type = "subt" value = "upload"/> <form> <!-1. 1. Multipart/Form-Data. Após definir esse valor, quando o navegador enviar o arquivo, ele anexará os dados do arquivo ao corpo da mensagem de solicitação HTTP e usará o protocolo MIME para descrever o arquivo carregado para facilitar o receptor para analisar e processar os dados enviados. 3. O atributo de entrada da entrada deve ser definido, caso contrário, o navegador não enviará os dados do arquivo carregado. ->
2. Leia os dados do upload de arquivo no servlet e salve -os no disco rígido do servidor
O objeto de solicitação fornece um método getInputStream, através do qual os dados enviados pelo cliente podem ser lidos. No entanto, como os usuários podem fazer upload de vários arquivos ao mesmo tempo, é uma tarefa muito problemática programar e ler diretamente os dados enviados no lado do servlet e analisar os dados de arquivo correspondentes separadamente.
Por exemplo, a seguir, é apresentado um dos conteúdos do protocolo HTTP da solicitação enviada pelo navegador interceptado ao fazer upload do arquivo:
Aceitar-Language: ZH-HANS-CN, ZH-HANS; Q = 0.5-CONTENTENTE: Multipart/Form-Data; Limite = --------------------------- 7DFA01D1908A4UA-CPU: AMD64CECT-CODE: GZIP, DeflateUser-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; X64; Tridente/7.0; Keep-alivepragma: no-cachecookie: JSessionID = 11CEFF8E271AB62CE676B5A87B746B5F --------------------------- 7DFA01D1908A4CONTENT-DISPOSIÇÃO: Form-Data; Nome = "Nome de usuário" Zhangsan ----------------------------- 7DFA01D1908A4CONTENT-DISPOSIÇÃO: FORM-DATA; name = "UserPass" 1234 ------------------------- 7DFA01D1908A4CONTENT-DISPOSIÇÃO: FORM-DATA; nome = "nome do arquivo1"; filename = "c: /users/asus/desktop/upload.txt" content-type: text/plany este é o primeiro conteúdo do arquivo! ----------------------------- 7DFA01D1908A4CONTENT-DISPOSIÇÃO: FORM-DATA; nome = "nome do arquivo1"; filename = "c: /users/asus/desktop/upload2.txt" content-type: text/plany este é o segundo conteúdo do arquivo! Hello ----------------------------- 7DFA01D1908A4--
Também pode ser visto nos dados acima que é difícil escrever um programa robusto e estável se você dividir e ler manualmente os dados. Portanto, para facilitar os usuários a processar dados de upload, o Apache Open Source Organization fornece um componente de código aberto (Commons-FileUpload) usado para processar uploads de arquivo. Esse componente tem um excelente desempenho e sua API é extremamente simples de usar, permitindo que os desenvolvedores implementem facilmente funções de upload de arquivos da Web. Portanto, no desenvolvimento da Web, a função de upload de arquivos é geralmente implementada usando o componente Commons-FileUpload.
Dois pacotes JAR precisam ser importados: Commons-FileUpload, Commons-Io
Response.setContentType ("Text/html; charset = utf-8"); // Definir resposta de codificação Request.SetcharAcTerEncoding ("UTF-8"); PrintWriter Writer = Response.getWriter (); // Obter resposta de saída ServletInputStream inputStream = request.getInputStream (); // Obter Solicitação de fluxo de entrada/** 1. Crie um DiskFileItemFactory com o objeto, defina o tamanho do buffer e o diretório de arquivos temporário*, há outros construtores de uma classe, um para um construtor sem o consultor, e o diretório de arquivos temporário*, há outros construtores, um dos dois construtores que é um construtor, um dos parâmetros de um construtor, e um dos parâmetros de um construtor, e um dos parâmetros de um construtor, e um dos parâmetros de um construtor, e o diretório de arquivos*, e o diretório de arquivos* e se há outros construtores. Sizethreshold, esse parâmetro define o tamanho do buffer de memória, o valor padrão é 10k. Quando o arquivo de upload for maior que o tamanho do buffer, o componente FileUpload fará o upload do arquivo usando o cache do arquivo temporário* @param java.io.file repositório, este parâmetro especifica o diretório de arquivos temporário, o valor padrão é o System.getProperty ("java.io.tmpdir"); * * Se um construtor sem parâmetros for usado, SetSizethReshold (int sizethreshold), setrepository (java.io.file repositório) * o método é definido manualmente */ diskFileItemFactory Factory = new DiskFileItemFactory (); int sizethreshold = 1024*1024; Factory.SetSizETHreshold (Sizethreshold); Arquivo repositório = novo arquivo (request.getSession (). GetServletContext (). GetRealPath ("temp")); // system.out.println (request.getSession (). GetServletContext () .getRealPath ("temp"); Factory.SetRepository (repositório); / * * 2. Use o objeto DiskFileItemFactory para criar um objeto ServletFileUpload e definir o tamanho do arquivo carregado * * O objeto ServletFileUpload é responsável pelo processamento dos dados do arquivo carregado e encapsular cada item de entrada no formulário em um arquivo * Setents deste objeto é: * Boolean IsmmmmmmiLTCOURCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTCENTE ( * Determine se o formulário carregado é multipart/formulário tipo* list parserequest (solicitação); analise o objeto de solicitação, envolva cada item de entrada no formulário em um objeto FileItem e retorne uma coleção de listas que salva todos os fileItems* void setFilesizEMAX (Long Fileizemax); Defina o valor máximo de um único arquivo carregado* void SetsizEMAX (Sizemax longo); Defina o valor máximo da quantidade total de upload wenjiang* void setheaderencoding (); Defina o formato de codificação para resolver o problema dos nomes de arquivos de upload de código iluminado*/ servletfileUpload upload = new ServletfileUpload (fábrica); upload.setheadeRencoding ("utf-8"); // Defina o formato de codificação para resolver o problema dos nomes de arquivos de código de código ilegal/** 3. Ligue para o Método ServletFileUpload.parsereQuest para analisar o objeto de solicitação e obter um objeto List que salva todo o conteúdo uploado*/list <ItemeM> parserel. tente {parserequest = upload.parserequest (request); } catch (fileUploadexception e) {e.printStackTrace (); } / * * 4. Itreate sobre a lista. Each iterate a FileItem object, call its isFormField method to determine whether it is a file upload* true means it is a normal form field, then call the getFieldName and getString methods to get the field name and field value * false is the upload file, and then call the getInputStream method to get the data input stream, thereby reading the upload data* * FileItem is used to represent an upload file object or an ordinary form object in the file upload form* The commonly Os métodos usados deste objeto são: * boolean isformfield (); Determina se o FileItem é um objeto de upload de arquivo ou um objeto de formulário normal * true significa que é um campo de formulário normal, * ligue para os métodos GetFieldName e GetString para obter o nome do campo e o valor do campo * false como o arquivo de upload, * ligue para getName () para obter o nome do arquivo do arquivo de upload. NOTA: Alguns navegadores carregam caminhos do cliente e precisam se subtrair * Call GetInputStream () para obter o fluxo de entrada de dados, para ler os dados de upload * delete (); significa que, após o fechamento do fluxo de entrada do FileItem, os arquivos temporários excluídos são excluídos. */for (fileItem fileItem: parserequest) {if (fileItem.isformfield ()) {// representa o campo normal if ("nome de usuário" .equals (fileItem.getFieldName ()))) {string userName = fileItem.getString (); writer.write ("Seu nome de usuário:"+nome de usuário+"<br>"); } if ("userPass" .equals (fileItem.getfieldName ())) {string userPass = fileItem.getString (); writer.write ("Sua senha:"+UserPass+"<br>"); }} else {// significa um arquivo carregado // Os arquivos carregados por diferentes navegadores podem ter um nome de caminho e você precisa cortar string clientname = FILEITEM.getName (); String filename = ""; if (clientname.contains ("//")) {// se "/" significa um nome com um caminho, o último nome do arquivo é interceptado FileName = clientName.substring (clientName.LastIndexOF ("//")). Substring (1); } else {filename = clientName; } Uuid randomuuid = uuid.randomuuid (); // gerar um identificador de 128 bits de comprimento, nome do identificador de 128 bits, nome do nome = randomuuid.toString ()+nome do arquivo; / * * Projete um algoritmo de geração de diretório. Se o número total de arquivos enviados pelo usuário for, ordens de milhões de ordens de magnitude ou mais, colocá -los no mesmo diretório faz com que o índice de arquivos seja muito lento. * Therefore, it is very necessary to design a directory structure to store files in a scattered manner, and reasonably * Convert the UUID hash algorithm to a smaller range, * Convert the hashcode of the UUID into an 8-bit eg octal string, * Starting from the first bit of this string, each character represents a first-level directory, so an eight-level directory is built, with up to 16 subdirectories in each level Diretório* Esta é uma estrutura de diretório muito eficiente para o servidor e o sistema operacional*/ int hashuuid = randomuuid.hashcode (); String hexuuid = Integer.toHexString (hashuuid); //System.out.println(hexuuid); // Obtenha o caminho absoluto para qual pasta armazenar o arquivo carregado em string filepath = request.getSession (). GetServletContext (). GetRealPath ("upload"); for (char c: hexuuid.toCharArray ()) {filepath = filepath+"/"+c; } // Se o diretório não existir, gerar um arquivo de diretório de oitavo nível filepathfile = novo arquivo (filepath); if (! filepathfile.exists ()) {filepathfile.mkdirs (); } // Leia o arquivo a partir do fluxo de entrada da solicitação e grave no servidor inputStream inputStream2 = FILEITEM.GETINPUPTSTREAM (); // Crie um arquivo no arquivo do lado do servidor Arquivo = novo arquivo (filepath+"/"+nome do arquivo); BufferOutputStream bos = new BufferoudOutputStream (new FileOutputStream (File)); byte [] buffer = novo byte [10*1024]; int len = 0; while ((len = inputStream2.read (buffer, 0, 10*1024))! =-1) {bos.Write (buffer, 0, len); } writer.write ("Você carregou o arquivo"+clientname+"com sucesso <br>"); // fechar o recurso bos.close (); inputStream2.close (); }} // Observe que o arquivo carregado do Eclipse está salvo no diretório de execução do projeto, não no diretório do projeto no espaço de trabalho.2. Questões que precisam de atenção especial ao upload de arquivos: (esses problemas são todos fornecidos com soluções simples no código acima)
1. Onde armazenar arquivos
Para garantir a segurança do servidor, o arquivo carregado deve ser salvo no diretório da Web-Inf do aplicativo ou um diretório não gerenciado pelo servidor da Web. Se o usuário enviar um arquivo com código executável, como um arquivo JSP, e acessar de acordo com o caminho de acesso de emenda, ele poderá fazer qualquer coisa no lado do servidor.
2. Para impedir que vários usuários enviem arquivos com o mesmo nome de arquivo, resultando em sobrescrição de arquivos, o upload de arquivos deve garantir que o arquivo carregado tenha um nome de arquivo exclusivo .
Renomear o nome do uuid + upload do usuário do usuário
Sobre Uuid:
UUID (identificador universalmente exclusivo) identificador globalmente exclusivo refere -se ao número gerado em uma máquina, o que garante que seja exclusivo de todas as máquinas ao mesmo tempo e espaço. De acordo com os padrões estabelecidos pela Open Software Foundation (OSF), endereço do cartão Ethernet, tempo de nanossegundos, código de identificação de chip e muitos números possíveis são usados. It consists of the combination of the following parts: the current date and time (the first part of the UUID is related to time. If you generate another UUID a few seconds after generating a UUID, the first part is different, the rest is the same), the clock sequence, the globally unique IEEE machine identification number (if there is a network card, it is obtained from the network card, and no network card is obtained in other ways), the only disadvantage of UUID é que a string de resultado gerada será relativamente longa.
É um número de 128 bits, geralmente expresso em hexadecimal. A idéia principal do algoritmo é gerar um GUID em combinação com a placa de rede da máquina, horário local e um número instantâneo. Teoricamente, se uma máquina gerar 100.000 guids por segundo, poderá ser garantida (no sentido de probabilidade) que 3240 anos não serão repetidos.
A partir do JDK1.5, a geração de UUIDs se tornou uma coisa simples, pensando que o JDK implementou UUIDs:
java.util.uuid, basta chamá -lo diretamente.
Uuid uuid = uuid.randomuuid ();
String s = uuid.randomuuid (). ToString (); // O ID da chave primária usado para gerar o banco de dados é muito bom. .
Uuid é composto por um número de dezesseis dígitos, que é expresso na forma de
550E8400-E29B-11D4-A716-446655440000
3. Para evitar muitos arquivos em um único diretório e afetar a velocidade de leitura e escrita de arquivos, o programa que lida com arquivos de upload deve escolher o algoritmo de geração de estrutura de diretório apropriado com base no volume total possível de upload e armazenar os arquivos enviados de maneira dispersa. Por exemplo, use o método HashCode para criar um diretório de vários níveis.
4. Se os usuários diferentes enviarem o mesmo arquivo, não há necessidade de armazenar muitas cópias do mesmo arquivo no lado do servidor. Este é um desperdício de recursos. Um algoritmo deve ser projetado para resolver o problema dos arquivos duplicados.
5. O Princípio da Tecnologia JSP implementa automaticamente a multi-threading. Portanto, os desenvolvedores não precisam considerar operações multithreads de upload de arquivos
3. Download do arquivo
<% ArrayList <String> filenames = new ArrayList <String> (); filenames.add ("file/aa.txt"); filenames.add ("file/bb.jpg"); para (string fileName: FILENames) { %> <form action = "DownloadServlet" Method = "get"> <input type = "Hidden" name = "FileName" value = "< %= nome do arquivo %>" /> <input Type = "submit" value = "Download: <1NameName FilEname>" /> < /". String filename = request.getParameter ("nome do arquivo"); String urlname = urlencoder.encode (nome do arquivo, "utf-8"); // impedir a resposta ilegal chinesa.setheader ("contentação de conteúdo", "anexo; nome do arquivo ="+urlname); FileInputStream fis = new FileInputStream (novo arquivo (request.getSession (). GetServletContext (). GetRealPath (FileName))); BufferInputStream bis = new bufferInputStream (fis); ServletOutputStream SOS = Response.getOutputStream (); byte [] buffer = novo byte [1024]; int len = 0; while ((len = bis.read (buffer, 0, 1024))! =-1) {sos.write (buffer, 0, len); } bis.close (); fis.close ();4. Use o componente SmartUpload no SSH para simplificar o upload de arquivos e baixar
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.