Este artigo apresenta como usar as bibliotecas disponíveis existentes no Java para escrever o código do cliente FTP e desenvolvê -lo nos controles de applet para fazer lotes, grandes arquivos carregar e baixar controles com base na web. Com base em uma série de bibliotecas de clientes da FTP, o artigo fornece explicações detalhadas e implementações de código em uma das bibliotecas J-FTP mais comuns e poderosas, como barras de progresso, continuação do ponto de interrupção, mapeamento de redes internas e externas e funções JavaScript de retorno de chamada no aplicativo. Espera -se que este artigo desempenhe um papel na atraição do Jade.
1. Introdução
Durante a implementação de um projeto, surgiu um requisito de upload e download de arquivo baseado na Web. Os usuários de toda a província (ou em todo o país) precisam fazer upload de alguns arquivos para o servidor de arquivos em um determinado centro. Esses documentos são usados para alguma construção de engenharia em larga escala, que pode envolver projetos de construção no valor de dezenas de milhões ou até centenas de milhões de yuan. Os arquivos têm três características distintas: uma é que o arquivo é grande, que pode atingir 50m; A segunda é que o número de arquivos é grande, o que pode ser de cerca de 15; A terceira é que as assinaturas digitais e a criptografia de dados são necessárias em termos de segurança de dados.
Primeiro de tudo, considere o método de transmissão baseado em HTTP. No entanto, através da comparação, descobri rapidamente que as necessidades acima foram atendidas:
1: O upload usando o protocolo HTTP parece ser mais adequado para a conveniência da programação da Web; O upload de arquivos menos de 1M é um pouco mais rápido do que o upload de arquivos usando o protocolo FTP. Mas pode não haver nada a fazer sobre a transferência de lotes e arquivos grandes. Obviamente, ele também tem suas vantagens, como diferente do FTP, é necessário iniciar um serviço FTP no lado do servidor.
2: O upload de arquivos com arquivos maiores que 1M usando o protocolo FTP é mais rápido que o HTTP. Quanto maior o arquivo, a velocidade de upload será várias vezes mais rápida que a velocidade de upload HTTP. E escrever programas em Java; O FTP é mais conveniente que o HTTP.
O autor já usou o VB e escreveu controles ActiveX para fazer upload e baixar arquivos em lote, e suas funções também são muito poderosas. É apenas que, como não existe uma assinatura digital especial para arquivos de táxi ou OCX, é necessário executar configurações tediosas para o cliente, como a configuração de um site seguro, reduzindo o nível de segurança do cliente etc., algumas soluções foram abandonadas.
Ao mesmo tempo, considerando que os arquivos precisam ser assinados e criptografados digitalmente no cliente, foi decidido usar o applet para implementá -los. . Antes de fazer o upload do arquivo, as informações principais locais do USBKEY podem ser obtidas do cliente para concluir o processamento de criptografia e assinatura do arquivo carregado. Embora o uso do applet exija a instalação do ambiente de tempo de execução do JRE no cliente, o que traz algum inconveniente ao gerenciamento e uso do cliente, pode ser um preço relativamente pequeno comparar a segurança de um número tão grande de arquivos e arquivos.
Para resumir o ambiente operacional:
Lado do servidor FTP: Servi-U, um programa profissional do lado do servidor FTP, existem downloads prontos de software na Internet, é claro que os leitores também podem escrever um programa de recebimento de arquivo FTP do lado do servidor para explicar. Se não houver requisitos ou funções especiais, o Serv-U deverá ser capaz de atender às nossas necessidades gerais de upload e download;
Cliente: Java Applet, uma tecnologia que tornava o Java Popular na época que afirmava ser comparável ao ActiveX da Microsoft. Claro, agora Java tem Java FX. É um substituto para o applet?
Ambiente de aplicativos: Internet, final final.
2. Escolha da Biblioteca de Clientes Java FTP
Vamos imaginar um cenário - queremos escrever um aplicativo Java puro que carregue e baixe arquivos de um servidor FTP em execução em um computador remoto; Também queremos obter informações básicas sobre o arquivo para esses arquivos remotos para download, como nome do arquivo, dados ou tamanho do arquivo.
Embora seja possível e talvez interessante escrever um manipulador de protocolo FTP do zero, o trabalho também é difícil, longo e potencialmente perigoso. Como não estamos dispostos a gastar tempo, energia ou dinheiro na redação de um programa de processamento, recorremos a componentes reutilizáveis que já existem. E muitas bibliotecas estão disponíveis online.
Encontrar uma excelente biblioteca de clientes Java FTP que atenda às nossas necessidades não é tão simples quanto parece. Pelo contrário, esta é uma tarefa muito dolorosa e complicada. Primeiro, leva algum tempo para encontrar uma biblioteca de clientes FTP. Segundo, depois de encontrarmos todas as bibliotecas existentes, qual devemos escolher? Cada biblioteca é adequada para diferentes necessidades. Essas bibliotecas não são equivalentes no desempenho e têm diferenças fundamentais em seu design. Cada biblioteca possui suas próprias características e usa termos diferentes para descrevê -los. Portanto, avaliar e comparar as bibliotecas de clientes FTP é uma tarefa difícil.
Usar componentes reutilizáveis é uma abordagem defendida, mas, neste caso, é frequentemente desencorajador no início. Mais tarde, posso ter um pouco de vergonha: depois de escolher uma boa biblioteca FTP, o trabalho subsequente é muito simples, basta seguir as regras simples. Atualmente, existem muitas bibliotecas de clientes FTP publicamente e gratuitas, como Simpleftp, J-FTP, etc. e muitos outros FTPClients. Conforme mostrado na tabela a seguir, a tabela não pode ser listada tudo. Se os leitores tiverem uma melhor biblioteca de classes FTP do cliente, faça mais suplementos.
Neste artigo, o autor adota J-FTP. Esta é uma biblioteca FTP de código aberto e muito poderosa. O autor gosta muito e também o recomenda a todos os leitores. Esqueça de graça e faça um anúncio para isso.
3. Funções básicas
1. Faça login
O FTP é usado para transferência de arquivos, mas, em essência, o java.net.socket é usado para comunicação. O código a seguir é apenas um dos métodos de login da classe net.sf.jftp.net.ftpConnection. Obviamente, para salvar o layout e explicar alguns princípios claramente no código a seguir, o autor removeu alguns códigos desnecessários, como logs e outros códigos. Para o código completo, consulte o código-fonte do J-FTP ou o código-fonte de exemplo do autor. Os seguintes exemplos de código são os mesmos:
public int Login (String UserName, String senha) {this.username = nome de usuário; this.password = senha; int status = login_ok; jcon = novo JConnection (host, porta); if (jcon.isthere ()) {in = jcon.getReader (); if (getLine (positivo) == null) // ftp220_service_ready) == null) {ok = false; status = offline; } if (! getLine (loginack) .startswith (positivo)) // ftp230_logged_in)) {if (succcess (positivo)) // ftp230_logged_in)) {} else {ok = false; status = hordas_login_data; }}} else {if (msg) {log.debug ("ftp não disponível!"); ok = false; status = genérico_failed; }} if (ok) {conectado = true; sistema(); binário(); String [] advSettings = new String [6]; if (getostype (). indexof ("os/2")> = 0) {list_default = "list"; } if (list.equals ("padrão")) {// Apenas obtenha o primeiro item (de alguma forma sabe que primeiro é o comando // ftp list) advSettings = loadSet.loadSet (Settings.adv_settings); // *** Se o arquivo não for encontrado, crie -o e defina -o como list_default if (advSettings == null) {list = list_default; Saveset s = new SaveSet (Settings.adv_settings, list); } else {list = AdvSettings [0]; if (list == null) {list = list_default; }}} if (getostype (). indexof ("mvs")> = 0) {list = "list"; } // *** FiredirectoryUpdate (this); FireConnectionEnitialized (isto); } else {fireConnectionFailed (isto, novo inteiro (status) .toString ()); } status de retorno; } Neste método de login, há uma classe JConnection, responsável pelo estabelecimento de soquetes. Ao mesmo tempo, esta classe é um encadeamento separado. A vantagem é que, para cooperar com alterações de interface, conexões de soquete de rede e outras tarefas são processadas como encadeamentos separados, o que é propício à simpatia da interface. Abaixo está o método de execução do net.sf.jftp.net.jConnection. Obviamente, a inicialização deste thread é iniciada no construtor da classe JConnection.
public void run () {try {s = new Socket (host, porta); Localport = s.getLocalport (); // if (horário> 0) s.SetSotimeout (tempo); out = new PrintStream (new BufferoudOutputStream (s.getOutputStream (), Settings.Buffersize)); in = new BufferredReader (new InputStreamReader (s.getInputStream ()), Settings.Buffersize); isok = true; //}} catch (Exceção ex) {ex.printStackTrace (); Log.out ("AVISO: conexão fechada devido à exceção (" + host + ":" + porta + ")"); isok = false; tente {if ((s! = null) &&! s.iscosed ()) {s.close (); } if (out! = null) {out.close (); } if (in! = null) {in.close (); }} catch (Exceção ex2) {ex2.printStackTrace (); Log.out ("Aviso: obteve mais erros tentando fechar o soquete e os fluxos"); }} estabelecido = true; }O soquete neste método de execução explicará aqui que esse tipo de implementação de soquetes do cliente (também chamado de "soquetes"), que são pontos de extremidade de comunicação entre duas máquinas. O trabalho real do soquete é executado por uma instância da classe SocketImpl. Um aplicativo implementa uma fábrica de soquete que cria soquetes alterando a fábrica de soquete que pode se configurar para criar soquetes adequados para o firewall local. Para instruções específicas, consulte as instruções da API do JDK5, de preferência em chinês. hehe.
2 Faça upload e download
O upload de arquivos pode ser dividido em thread e thread único, o que é relativamente simples em situações de thread único, enquanto em situações com vários threads, mais coisas a serem tratadas e mais cuidadosas. Abaixo está o método do manipulador de upload do net.sf.jftp.net.ftpConnection. Dois tipos diferentes, rosca única e multi-thread, foram considerados.
public int handleUpload (arquivo de string, string realname) {if (Settings.getEnableMultithReading () && (! Settings.getNouploadMultithReading ())) {log.out ("Spawing novo thread para este upload"); FtpTransfer t; if (realname! = null) {t = novo ftpTransfer (host, porta, getLocalPath (), getCachedPwd (), arquivo, nome de usuário, senha, transfer.upload, manipulador, ouvintes, nome real, crlf); } else {t = novo ftpTransfer (host, porta, getLocalPath (), getCachedPwd (), arquivo, nome de usuário, senha, transfer.upload, manipulador, ouvintes, CRLF); } lastTransfer = t; retornar new_transfer_spawned; } else {if (Settings.getNouPloadMultithReading ()) {Log.out ("Upload multithreading está desativado."); } else {log.out ("O multithreading está completamente desativado."); } return (realname == null)? upload (arquivo): upload (arquivo, nome real); }} No caso de multi-threading, há uma classe separada net.sf.jftp.net.ftptransfer. Obviamente, no caso de multi-threading, essa classe deve ser um encadeamento separado. Semelhante à JConnection, a startup de seu thread também é iniciada no construtor. Em seu método de execução, o arquivo é lido e transmitido.
public void run () {if (handler.getConnections (). get (file) == null) {handler.addConnection (arquivo, this); } else if (! pause) {log.debug ("transferência já em andamento:" + arquivo); trabalho = falso; stat = 2; retornar; } boolean haspaused = false; while (pausa) {tente {runner.sleep (100); if (ouvintes! = null) {for (int i = 0; i <ouvintes.size (); i ++) {((ConnectionListener) ouvintes.elementat (i)). updateProgress (arquivo, pausado, -1); }} if (! work) {if (ouvintes! = null) {for (int i = 0; i <ouvintes.size (); i ++) {((ConnectionListener) ouvintes.Elementat (i)). UpdateProgress (arquivo, removido, -1); }}}} catch (Exceção ex) {} haspaised = true; } while ((handler.getConnectionSe ()> = settings.getMaxConnections ()) && (handler.getConnectionsize ()> 0) && work) {try {stat = 4; corredor.sleep (400); if (! haspaised && (ouvintes! = null)) {for (int i = 0; i <ouvintes.size (); i ++) {((ConnectionListener) ouvintes.Elementat (i)). UpdateProgress (arquivo, fila, -1); }} else {break; }} catch (Exceção ex) {ex.PrintStackTrace (); }} if (! work) {if (ouvintes! = null) {for (int i = 0; i <ouvintes.size (); i ++) {((ConnectionListener) ouvintes.Elementat (i)). UpdateProgress (arquivo, removido, -1); }} handler.removeConnection (arquivo); stat = 3; retornar; } iniciado = true; tente {runner.sleep (Settings.ftpTransferThreadPause); } catch (Exceção ex) {} con = new ftpConnection (host, porta, remotepath, CRLF); Con.SetConnectionHandler (Handler); Con.SetConnectionListeners (ouvintes); int status = con.login (usuário, pass); if (status == ftpConnection.login_ok) {arquivo f = new File (localPath); Con.SetLocalPath (F.GetabsolutePath ()); if (type.equals (upload)) {if (newName! = null) {transferstatus = con.upload (arquivo, newName); } else {transferstatus = con.upload (arquivo); }} else {transferstatus = con.download (arquivo, this.newname); }} if (! pause) {handler.removeConnection (arquivo); }} Quanto ao processo de download, porque é um processo inverso do upload, é semelhante ao método de upload e ao método de escrita. Por algumas razões, o código não está listado, mas suas idéias e idéias são exatamente as mesmas. Consulte o código -fonte para os leitores.
4. Barra de progresso
Pode -se imaginar que, se não houver prompt durante o processo de upload ou download, o usuário não poderá julgar se a tarefa é concluída ou se a tarefa está morta, e o usuário geralmente é enganoso devido ao tempo de upload ou ao tempo de download muito longo. Portanto, a barra de progresso é muito importante e prática.
A implementação da barra de progresso é realmente muito simples. É para abrir dois tópicos no programa. O primeiro thread é usado para alterar dinamicamente o valor da barra de progresso na interface, enquanto o segundo encadeamento forma um loop durante o processo de upload ou download. Nesse loop, um certo número de dados como 8192 bytes são lidos a cada vez. Depois de passar esses dados, ligue para o método UpdateProgress no primeiro thread para atualizar o valor da barra de progresso da interface.
Durante o processo de upload ou download (consulte o método de execução da classe ftptransfer na seção anterior), você pode visualizar o método Con.Upload (arquivo, newname), o código é o seguinte.
public int upload (arquivo de string, string realname, inputStream in) {hasUploaded = true; Log.out ("O upload FTP começou:" + this); int stat; if ((in == null) && new File (arquivo) .isdirectory ()) {shortProgress = true; FileCount = 0; BaseFile = arquivo; datatype = dataconnection.putdir; isdirupload = true; stat = uploaddir (arquivo); shortProgress = false; //System.out.println(FileCount + ":" + BaseFile); FireProgressUpdate (BaseFile, DataConnection.dfinished + ":" + FileCount, -1); FireActionfinished (isto); FiredirectoryUpdate (isto); } else {datatype = dataconnection.put; stat = RawUpload (arquivo, nome real, IN); tente {thread.sleep (100); } catch (Exceção ex) {} FireActionFinished (this); FiredirectoryUpdate (isto); } tente {thread.sleep (500); } catch (Exceção ex) {} retornar stat; }Este método é responsável por enviar um certo número de bytes. De fato, é chamado de método RawUpload. Não está listado aqui. Consulte o código -fonte. Depois de passar esses dados de bytes, o método updateProgressBar () no encadeamento principal é chamado chamando o método FireActionFinished (). Na verdade, o código é o seguinte:
Void Protected UpdateProgressBar () {int percentual = (int) (((float) lfileCompleteSize / (float) lfilesize) * 10000f); pbfile.setValue (porcentagem); // System.out.println ("=================================================="+por cento); pbfile.SetString (lfileCompleteSize / 1024L + " /" + lfilesize / 1024L + "kb"); porcentagem = (int) (((float) ltotalCompleTesize / (float) ltotalsize) * 10000f); PBTOTAL.SETSTRING (LTOTALCOMPLETESIZE / 1024L + " /" + LTOTALSIZE / 1024L + "KB"); pbtotal.setValue (porcentagem); repintar (); } Duas barras de progresso são usadas acima. A primeira barra de progresso representa o progresso do upload ou download do arquivo atual, e a segunda barra de progresso representa o progresso de todos os arquivos baixar ou fazer upload. Ao mesmo tempo, para gerar uma progressão ou mudança de progresso mais óbvias, o valor máximo da barra de progresso é definido como 10.000 através do pbfile.setMaximum (10000) e pbtotal.setMaximum (10000), em vez dos 100 que geralmente definimos. O autor acredita que isso é melhor, porque às vezes ao fazer upload ou download, as alterações podem ser relativamente pequenas devido a razões de rede. Se definido como 100, a mudança não é particularmente óbvia.
O acima é o artigo básico para fazer upload e baixar grandes lotes de arquivos FTP. Espero que seja útil para o aprendizado de todos, e espero que todos apoiem mais o wulin.com.