NTLM認証のサイトからファイルをダウンロードする

SpringBootで作成中のアプリに、企業内のWebサイトよりエクセルファイルをダウンロードする要件があったので、何となくBasic認証のサイトだろうなと思い込んで実装を始めましたが全然繋がりません。

wget ‘http://username:password@filestore.bbb.co.jp/web/download/downloadfile.xlsx’
でファイルは取れます。

でも、
curl ‘http://username:password@filestore.bbb.co.jp/web/download/downloadfile.xlsx’
では動きません。

試しにwgetをデバッグモードでやってみて気が付きました。。

WWW-Authenticate: NTLM

このサイト、NTLM認証ですね。。

下記を参考に認証箇所を変更
http://code-addict.pl/reporting-services-rest-url-client/

また依存が増えてしまいましたが。。

       <dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpclient</artifactId>
		<version>4.5.6</version>
	</dependency>

ダウンロードファイルが更新されていた時だけダウンロードするという対応も必要なので、サーバ内にダウンロードしたローカルファイルとサイト上のファイルタイムスタンプをチェックし、一致しなければファイルをダウンロードしタイムスタンプをサイト上と同じ時間に書き換えるという対応になりました。

で、タイムスタンプはどこ?ここに書いてました。

確かにhttpヘッダに
Last-Modified:Tue, 14 Aug 2018 08:53:30 GMT
と書いてあります。

結局、こんな感じのコンポーネントを用意しました。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

@Component
public class FileDownLoader {
	public void donwLoadFile(String fileName) throws IOException, ParseException{

		FileTime beforeT = null;
        Path path = Paths.get("/localpath/" + fileName);
		try{
			//更新前ファイルのタイムスタンプ取得
			beforeT = Files.getLastModifiedTime(path);
		} catch (Exception ex) {
			//新規ファイル
		}
        String url = "http://filestore.bbb.co.jp/web/download/" +fileName;
    	CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                 new NTCredentials("username", "password", null, null));
        HttpGet httpGet = new HttpGet(url);
         
        CloseableHttpClient httpclient = HttpClientBuilder
                 .create()
                 .setDefaultCredentialsProvider(credentialsProvider)
                 .build();
         
        CloseableHttpResponse closeableHttpResponse = httpclient.execute(httpGet);
         
        FileTime modTime = beforeT;
        if( closeableHttpResponse.getAllHeaders() != null){
        	DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
        	modTime = FileTime.from(df.parse(closeableHttpResponse.getFirstHeader("Last-Modified").getValue()).toInstant());
        }
        //更新無し
		if(beforeT != null && beforeT.compareTo(modTime) == 0){
			closeableHttpResponse.close();
			return;
		}
        Files.write(path, EntityUtils.toByteArray(closeableHttpResponse.getEntity()));
        //更新日時タイムスタンプ書き換え
        Files.setLastModifiedTime(path, modTime);
		closeableHttpResponse.close();
	}
}

テストしてみます。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = UoeautomailApplication.class)
public class DownloadTest throws Exception{

	@Autowired
	FileDownLoader fileDownLoader;

 	@Test
	public void test(){
  	   	fileDownLoader.donwLoadFile("aaa.xlsx");
	}
}

とりえあず、動いたので整理してから実装します。

カテゴリー: Java   作成者: bokusui パーマリンク

bokusui について

ソフトウェアハウスでのPG・SEから始まり、10年近く勤めた金融系企業の社内SEを数年前にやめ、フリーランス時代を経たのち法人成りしました。システム開発の全工程をこじんまりとやり続けています。