Para deixar o código principal mais limpo e fácil de entender, vamos criar algumas funções auxiliares e deixá-las antes do fim da classe principal, ou seja, antes da ultima chave (}).
Insira as funções abaixo:
//########### funções auxiliares ############
private void downloadDow(int jornal, final String DATA){
//variável tipo bool para apagar os arquivos individuais
boolean delFiles = !jCheckBox6.isSelected();
//objeto tipo Lista para guardar o caminho e nome de cad arquivo baixado
ArrayList<String> downloadedFiles = new ArrayList();
//link para o site da imprensa nacional que mostra o número de páginas de cada caderno
String link = "http://www.in.gov.br/visualiza/index.jsp?jornal="+jornal+"&pagina=1&data="+DATA;
//captura o código fonte HTML do link acima, algo como vizualizar o código fonte da página no browser.
String fonte_html = getHtmlCode(link).toString();
//pega número de páginas do jornal
int numPgs = Integer.parseInt(
fonte_html.substring(fonte_html.indexOf("totalArquivos=")+14, fonte_html.indexOf("\" scrolling")).trim()
);
//Download página por página
try{
for(int i=1; i<numPgs+1; i++){
//atualiza o label3 com o progresso atual
jLabel3.setText("Baixando DOU "+jornal+" página "+i+" de "+numPgs);
//nome do arquivo invidual
String fileName = jTextField2.getText()+"pg_"+i+"_dou_"+jornal+".pdf";
//stream para o arquivo PDF do site
FileOutputStream output = new FileOutputStream(fileName);
//link para o site da imprensa nacional de onde os cadernos/jornais serão baixados
String site = "http://www.in.gov.br/servlet/INPDFViewer?jornal="+jornal+"&pagina="+i+"&data="+DATA+"&captchafield=firistAccess";
URL url = new URL(site);
//cria uma conexão HTTP e um buffer de dados contendo o PDF em si
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
BufferedInputStream input = new BufferedInputStream(conn.getInputStream());
byte[] buf = new byte[4096];
int len;
//baixa o PDF
while ( (len = input.read(buf)) > 0 )
output.write(buf, 0, len);
conn.disconnect();
input.close();
output.close();
//adiciona o nome do PDF baixado a uma lista de exclusão
if(delFiles)
downloadedFiles.add(fileName);
}
//Mescla os arquivos em 1 único
List<InputStream> sourcePDFs = new ArrayList<InputStream>();
final String OUTPT_FILENAME = "DOU_"+DATA.replace("/", ".")+"_Jornal_"+jornal+".pdf";
for(int i=1; i<numPgs+1; i++){
jLabel3.setText("Aguarde... Criando "+OUTPT_FILENAME);
String fileName = jTextField2.getText()+"pg_"+i+"_dou_"+jornal+".pdf";
sourcePDFs.add(new FileInputStream(new File(fileName)));
}
//mescla
PDFMergerUtility mergerUtility = new PDFMergerUtility();
mergerUtility.addSources(sourcePDFs);
mergerUtility.setDestinationFileName(jTextField2.getText()+OUTPT_FILENAME);
mergerUtility.mergeDocuments();
//Apaga os arquivos individuais se o jCheckBox6 estiver desmarcado
for(String sfile: downloadedFiles){
new File(sfile).delete();
}
}catch(Exception e){e.printStackTrace();}
}
final public File chooseFolder(){
//seleciona a pasta onde os arquivos PDF serão baixados
File file = null;
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Selecione o diretório.");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setMultiSelectionEnabled(false);
if (fc.showOpenDialog(null) != JFileChooser.CANCEL_OPTION)
file = fc.getSelectedFile();
else file = null;
return file;
}
public static StringBuilder getHtmlCode(String endereco) {
//pega o "código fonte" em HTML da página e salva em um objeto tipo StringBuilder
BufferedReader in = null;
StringBuilder ret = new StringBuilder("");
try {
URL url = new URL(endereco);
in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
ret.append(str);
}
} catch (Exception ex) { ex.printStackTrace(); }
finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
}
}
}
return ret;
}
private void ajeitaForm(){
this.setLocationRelativeTo(null);
jLabel3.setVisible(false);
jProgressBar1.setVisible(false);
}
private void marcaTodos() {
if(jCheckBox1.isSelected()){
jCheckBox2.setSelected(true);
jCheckBox3.setSelected(true);
jCheckBox4.setSelected(true);
jCheckBox5.setSelected(true);
} else{
jCheckBox2.setSelected(false);
jCheckBox3.setSelected(false);
jCheckBox4.setSelected(false);
jCheckBox5.setSelected(false);
}
}
private void terminado() {
jProgressBar1.setVisible(false);
jLabel3.setVisible(false);
jTextField1.setEditable(true);
jPanel2.setVisible(true);
jButton1.setEnabled(true);
jButton2.setVisible(true);
jCheckBox6.setVisible(true);
JOptionPane.showMessageDialog(rootPane, "Processo concluído!");
}
private void preparaFrame() {
jProgressBar1.setValue(0);
jProgressBar1.setVisible(true);
jLabel3.setVisible(true);
//não queremos que o usuário clique nisso durante o processo:
jTextField1.setEditable(false);
jPanel2.setVisible(false);
jButton1.setEnabled(false);
jButton2.setVisible(false);
jCheckBox6.setVisible(false);
}
private boolean verificaFrame() {
//verifica se a data do DOU foi informada
if(jTextField1.getText().equals("")){
JOptionPane.showMessageDialog(null, "Primeiro informe a data!");
jTextField1.grabFocus();
return false;
//verifica se pelo menos 1 caderno foi selecionado
} else if(jCheckBox2.isSelected()==false && jCheckBox3.isSelected()==false &&
jCheckBox4.isSelected()==false && jCheckBox5.isSelected()==false){
JOptionPane.showMessageDialog(null, "Informe uma seção do DOU para baixar!");
return false;
} else if(jTextField2.getText().equals("Selecione a pasta:")){
JOptionPane.showMessageDialog(null, "Informe a pasta de destino!");
return false;
}
return true;
}
Depois de colado este código, vá até o construtor da classe a chame a função
ajeitaForm(). Seu construtor deve ficar como abaixo:
/** Creates new form frame */
public frame() {
initComponents();
ajeitaForm();
}
Agora, queremos que quando o usuário clique no botão
BAIXAR D.O.U, todo o processo aconteça automaticamente:
- Download dos DOU 1 por 1;
- Criação de 1 pra cada jornal selecionado;
- Apagamento ou não dos PDFs individuais, com barra de progresso e status.
Para isso, volte até a parte visual do seu projeto e dê um duplo clique no botão
BAIXAR D.O.U. O NetBeans deve criar uma função automaticamente, conforme abaixo, e te mandar para o código de volta:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
Dentro da função acima, vamos chamar a função
verificaFrame() e depois criar um
SwingWorker, para que a barra de progresso possa funcionar, caso contrário, ela ficará congelada durante todo o processo e será inútil.
Antes de iniciar o processo, precisamos esconder/desabilitar tudo o que não queremos que o usuário mexa enquanto o programa estiver funcionando, pois a curiosidade matou o gato, por isso, chamaremos a função
preparaFrame(). Depois de tudo terminado, habilitaremos tudo para que ele possa baixar outro DOU caso queira.
Seu código dentro da função
jButton2ActionPerformed(), gerada automaticamente deve ser conforme abaixo:
// checa o preenchimento
if( verificaFrame() == false)
return;
//começa proceço:
new SwingWorker() {
@Override
protected Object doInBackground() throws Exception {
try{
preparaFrame();
final String DATA = jTextField1.getText();
boolean jn1= false, jn2= false, jn3= false, jn1000= false;
if(jCheckBox2.isSelected()) jn1 = true;
if(jCheckBox3.isSelected()) jn2 = true;
if(jCheckBox4.isSelected()) jn3 = true;
if(jCheckBox5.isSelected()) jn1000 = true;
//faz download dos DOU selecionados
if(jn1){ downloadDow(1, DATA); }
jProgressBar1.setValue(25);
if(jn2){ downloadDow(2, DATA); }
jProgressBar1.setValue(50);
if(jn3){ downloadDow(3, DATA); }
jProgressBar1.setValue(75);
if(jn1000){ downloadDow(1000, DATA); }
jProgressBar1.setValue(100);
}catch(Exception e ){
e.printStackTrace();
jProgressBar1.setValue(100);
}
return null;
}
@Override
protected void done() {
terminado();
}
}.execute();
Por último, faça o mesmo que foi feito com o
jButton2 com o
jButton1, e insira este código para que o usuário possa escolher onde salvar os DOUs baixados:
File f = chooseFolder();
if(f!=null) jTextField2.setText(f.getAbsolutePath()+"\\");
E chame
marcaTodos() na
jCheckBox1, quando for marcada ou desmarcada.
Seu código entre a função
jButton2ActionPerformed() e as declarações de variáveis globais geradas automaticamente pelo NetBeans, deve se parecer com isso:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
File f = chooseFolder();
if(f!=null) jTextField2.setText(f.getAbsolutePath()+"\\");
}
private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {
marcaTodos();
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new frame().setVisible(true);
}
});
}
Feito isso, basta compilar o programa e distribuí-lo com cada API PDFBox. Para facilitar o processo de distribuição, sugiro ver minha dica:
Para visualizar o código fonte completo deste artigo, visite meu blog:
Abraço a todos e muito obrigado.