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/
また依存が増えてしまいましたが。。
| 1 2 3 4 5 |        <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
と書いてあります。
結局、こんな感じのコンポーネントを用意しました。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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(); 	} } | 
テストしてみます。
| 1 2 3 4 5 6 7 8 9 10 11 12 | @RunWith(SpringRunner.class) @SpringBootTest(classes = UoeautomailApplication.class) public class DownloadTest throws Exception{ 	@Autowired 	FileDownLoader fileDownLoader;  	@Test 	public void test(){   	   	fileDownLoader.donwLoadFile("aaa.xlsx"); 	} } | 
とりえあず、動いたので整理してから実装します。
