自動跳轉的下載地址,用 curl 下載怎樣保留原檔名?

語言: CN / TW / HK

自動跳轉的下載地址,用 curl 下載怎樣保留原檔名?

本文已參與「新人創作禮」活動,一起開啟掘金創作之路。

最近在寫 Jenkinsfile 的時候遇到了一個場景,需要從一條連結地址下載 jar 包,jar 包名字是帶版本號的,我是希望不改變原來檔名的情況下去下載到某個目錄下。

一開始覺得這個場景需求不難哦,首先想到的是用我比較熟的 curl 命令直接下載就應該就可以了,馬上開工!

第一次失敗

我們這次要下載的連結長這樣(用 log4j-api 的倉庫地址舉例):

sh http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.apache.logging.log4j&a=log4j-api&v=LATEST

先用瀏覽器開啟一下連結,看看能不能正常下載:

download-browser

沒有問題,而且自動下載了最新版本的 jar 包,名字叫 log4j-api-2.14.1.jar ,完美的很,現在馬上轉戰 curl 命令。

ssh $ curl -O http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.apache.logging.log4j&a=log4j-api&v=LATEST

這個大寫的 -O 引數表示不需要指定檔名,用連結的檔名字來作為檔名。

一個回車下去,問題來了:

curl-fail-1

出現了很多奇奇怪怪的東西,而且下載下來的檔名變成了 'redirect?r=central-proxy'

我們來 cat 一下這個檔案看看裡面有什麼線索:

curl-fail-2

原來是返回了一個 400 - Bad Request 的頁面,看來是我們的地址有點問題,我們一起來仔細看看這條地址,其實可以看到地址後面有好幾個引數:

r=central-proxy&g=org.apache.logging.log4j&a=log4j-api&v=LATEST

可以看到裡面帶了個 & 符號,這個符號在 Linux 裡是指後臺執行,所以我們的地址還不能直接用。

知識點一:

這裡可以有兩種方法解決問題:

  • 轉義 url,將 & 前增加反斜槓 \&
  • curl -d 引數來傳參,並且強制使用 GET 方法 -G

```sh

方法一:轉義 url

$ curl -O http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy\&g=org.apache.logging.log4j\&a=log4j-api\&v=LATEST

方法二:用 curl -d 引數

$ curl -O -G \ http://repository.sonatype.org/service/local/artifact/maven/redirect \ -d "r=central-proxy&g=org.apache.logging.log4j&a=log4j-api&v=LATEST" ```

小插播:

歡迎關注我的 VX 號:叨叨技術 (daodao_tech)
前沿技術,深度評測
原創文章,首發公眾

第二次失敗

通過上面兩個方法我們又下載了一個東西:

curl-fail-3

從截圖可以看到,我們下載下來的檔名還是不太對,叫做 'redirect?r=central-proxy&g=org.apache.logging.log4j&a=log4j-api&v=LATEST',並不是我們想要的 log4j-api-2.14.1.jar

我們繼續 cat 一下它:

file

這次檔案裡面的內容不一樣了,裡面返回了一段話:

text If you are not automatically redirected use this url: http://repository.sonatype.org/service/local/repositories/central-proxy/content/org/apache/logging/log4j/log4j-api/2.14.1/log4j-api-2.14.1.jar

蕪湖,起碼伺服器正確返回了我們想要的下載地址,但是為什麼我們還是下載不到呢?

知識點二:

從內容可以猜測,伺服器其實是想重定向到裡面真正的下載地址讓我們下載,我們可以通過引數 curl -i 來列印 HTTP 的頭來看看:

file

從截圖可以看到,伺服器返回了 HTTP 307 的狀態碼,而且 Header 裡面有 location 的引數,所以證實了我們的想法,那怎麼讓 curl 去自動重定向到伺服器返回的地址呢?

知識點三:

這裡我們可以通過用 curl -L 引數來解決問題,-L 引數表示 Follow redirects,就是說告訴 curl 自動重定向到新的連結。

第三次失敗

感覺要解決這個問題了!我們馬上試下:

sh $ curl -O -L http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy\&g=org.apache.logging.log4j\&a=log4j-api\&v=LATEST

file

啊哈,好像成功下載到東西了!從截圖可以看到它下載了 293k 的東西,跟我們從瀏覽器下載的大小一樣。

但是!為啥檔名還是不對呢,並不是我們想要的 log4j-api-2.14.1.jar

知識點四:

雖然我們用了 curl -L 引數實現了自動重定向到下載連結,但是 curl -O 引數只會用到最開始的地址作為下載的檔名。

第四次嘗試

既然不能直接 curl -O ,那有沒有辦法先拿到真正的下載地址,再用 curl -O 去請求地址,那不是可以保留原檔名下載了嗎?

先上命令程式碼:

sh $ curl -I -L -s http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy\&g=org.apache.logging.log4j\&a=log4j-api\&v=LATEST \ -o /dev/null \ -w %{url_effective}

知識點五: 這個命令裡面有很多知識點要介紹下:

  1. curl -I 引數表示只打印資訊,不會真正下載
  2. curl -s (小寫)引數表示靜默模式
  3. curl -o /dev/null (小寫)表示將輸出的東西重定向到 /dev/null 丟棄
  4. curl -w %{url_effective}(小寫)表示輸出最後的 url 地址

所以通過上面的命令,我們能夠獲取到最後的下載地址了:

file

第五次成功

既然我們都獲取到真正的下載地址了,那麼我們拿著這個地址再用 curl -O 就可以達到我們想要的效果了。

立刻上程式碼:

sh $ curl -I -L -s http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy\&g=org.apache.logging.log4j\&a=log4j-api\&v=LATEST \ -o /dev/null \ -w %{url_effective} \ | xargs curl -O

file

終於成功! 我們再優化一下上面的命令,可以得到最後我們要的命令程式碼:

sh $ curl -GILs http://repository.sonatype.org/service/local/artifact/maven/redirect \ -d "r=central-proxy&g=org.apache.logging.log4j&a=log4j-api&v=LATEST" \ -o /dev/null \ -w %{url_effective} \ | xargs curl -O

最後

歡迎關注我的 VX 號:叨叨技術 (daodao_tech)

前沿技術,深度評測

原創文章,首發公眾

叨叨技術二維碼