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

語言: CN / TW / HK

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

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

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

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

第一次失敗

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

sh https://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 https://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 https://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 \ https://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: https://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 https://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 https://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 https://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 https://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)

前沿技術,深度評測

原創文章,首發公眾

叨叨技術二維碼