curl tải tệp an toàn: Lưu, kiểm tra và xác minh phản hồi
Học quy trình tải bằng curl an toàn: lưu vào tệp tạm, xử lý chuyển hướng, dừng khi HTTP lỗi, kiểm tra Content-Type và kích thước, xác minh checksum, tiếp tục có điều kiện và loại bỏ nội dung bất thường.
Tác giảYiyao
Một quy trình tải tệp bằng curl đáng tin cậy không chỉ là truyền URL cho một lệnh. Hãy ghi vào tệp tạm, xử lý chuyển hướng một cách có chủ ý, coi lỗi HTTP là lỗi, lưu lại siêu dữ liệu phản hồi rồi kiểm tra các byte đã nhận trước khi giao tệp cho chương trình khác.
Các ví dụ dùng endpoint công khai https://httpbin.org/bytes/1024, trả về 1.024 byte. Khi áp dụng thực tế, chỉ truy cập URL mà bạn được phép sử dụng và đặt giới hạn dung lượng đĩa trước khi tải dữ liệu do người khác kiểm soát.
Bắt đầu bằng tệp tạm và giới hạn kích thước
Tệp tạm giúp cách ly phản hồi chưa hoàn tất hoặc không đúng định dạng khỏi đường dẫn cuối cùng. Trap dọn tệp khi lệnh kết thúc, còn --max-filesize tạo một lớp bảo vệ sớm. Sau khi tải vẫn phải kiểm tra số byte thực tế vì máy chủ có thể dùng truyền theo chunk hoặc không gửi Content-Length.
set -eu
url='https://httpbin.org/bytes/1024'
tmp="$(mktemp "${TMPDIR:-/tmp}/arcvenza-curl.XXXXXX.bin")"
trap 'rm -f "$tmp"' EXIT
curl --location --fail --show-error --silent \
--output "$tmp" \
--max-filesize 10485760 \
"$url"
received="$(wc -c < "$tmp")"
test "$received" -le 10485760
printf 'saved=%s bytes\n' "$received"
Nếu cần giữ kết quả, hãy tách đường dẫn tạm khỏi đường dẫn đích. Với URL do người dùng cung cấp, dịch vụ cũng nên giới hạn dung lượng trống và thời gian lưu ở bên ngoài curl.
Hiểu các tùy chọn chính
-L hoặc --location theo các chuyển hướng HTTP. -o hoặc --output ghi phản hồi vào đúng đường dẫn bạn chọn thay vì in nội dung ra terminal. --fail trả về mã thoát khác 0 khi gặp HTTP 400 trở lên, giúp tránh coi trang đăng nhập hoặc trang lỗi là tệp đã tải thành công. --show-error kết hợp với --silent để ẩn thanh tiến trình nhưng vẫn giữ thông tin chẩn đoán.
curl -L --fail --show-error --silent \
-o "$tmp" \
"https://httpbin.org/bytes/1024"
Hãy kiểm tra mã thoát của tiến trình trước khi đọc tệp. Thành công ở tầng truyền tải chỉ cho biết curl hoàn thành yêu cầu; điều đó không chứng minh nội dung có đúng định dạng mà ứng dụng mong đợi.
Ghi lại trạng thái, Content-Type và Content-Length
Lưu các header phản hồi và yêu cầu curl in ra trạng thái cuối, loại media mà curl nhận diện và số byte đã ghi. Kích thước trong write-out là số byte curl thực sự ghi, còn Content-Length là header do máy chủ cung cấp. Sau chuyển hướng, tệp header có thể chứa nhiều khối phản hồi; khi cần phân biệt chính xác, hãy xem khối cuối.
headers="$(mktemp "${TMPDIR:-/tmp}/arcvenza-curl-headers.XXXXXX")"
trap 'rm -f "$tmp" "$headers"' EXIT
curl --location --fail --show-error --silent \
--dump-header "$headers" \
--output "$tmp" \
--write-out 'status=%{http_code}\ncontent_type=%{content_type}\nreceived=%{size_download}\n' \
"https://httpbin.org/bytes/1024"
grep -iE '^(content-type|content-length):' "$headers" || true
Content-Type là lời tuyên bố về loại dữ liệu, không phải bằng chứng rằng các byte chính xác. Content-Length hữu ích để lập kế hoạch và đối chiếu, nhưng có thể vắng mặt khi phản hồi được stream hoặc nén. Nếu máy chủ cung cấp cả hai, hãy so sánh độ dài được quảng cáo với số byte nhận được.
Kiểm tra loại tệp, checksum và nội dung nhận được
Khi biết định dạng mong đợi, hãy dùng công cụ nhận diện loại tệp và hash mật mã. Với một artifact cố định, so sánh SHA-256 với giá trị đáng tin cậy do nhà phát hành cung cấp. Tên tệp hoặc Content-Type không đủ để chứng minh định dạng.
file "$tmp"
sha256sum "$tmp"
python3 - "$tmp" <<'PY'
from hashlib import sha256
from pathlib import Path
import sys
path = Path(sys.argv[1])
with path.open("rb") as stream:
first = stream.read(512)
if first.lstrip().lower().startswith((b"<!doctype html", b"<html")):
raise SystemExit("đã nhận HTML thay vì tệp mong đợi")
digest = sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
print(f"bytes={path.stat().st_size}")
print(f"sha256={digest.hexdigest()}")
Trên Windows, các bước tương đương là Get-Item, Get-FileHash -Algorithm SHA256 và Format-Hex -Count 16. Với định dạng đã biết, hãy dùng parser của định dạng đó để kiểm tra cuối cùng; kiểm tra magic byte chỉ bắt được những sai khác rõ ràng.
$path = Join-Path $env:TEMP 'arcvenza-curl.bin'
curl.exe -L --fail --show-error --silent --output $path 'https://httpbin.org/bytes/1024'
Get-Item $path
Get-FileHash $path -Algorithm SHA256
Format-Hex -Path $path -Count 16
Chỉ tiếp tục tải khi điều kiện phù hợp
-C - hoặc --continue-at - yêu cầu curl tiếp tục từ độ dài hiện có của tệp. Chỉ dùng khi máy chủ hỗ trợ byte range và bạn biết tệp cục bộ là bản chưa hoàn tất của đúng object đó. Nếu URL, representation hoặc cách nén thay đổi, hãy bắt đầu lại bằng một tệp tạm mới.
curl --location --fail --show-error --silent \
--continue-at - \
--output "$tmp" \
"https://httpbin.org/bytes/1024"
Tải tiếp vẫn phải qua cùng quy trình xác minh như tải mới: kiểm tra mã thoát, đối chiếu kích thước cuối, kiểm tra nội dung và xác minh checksum đáng tin cậy nếu có. Đừng nối một phản hồi chưa kiểm tra vào tệp chỉ vì lệnh đã trả về dữ liệu.
Tiêu chí nghiệm thu
Quy trình đạt yêu cầu khi dùng URL công khai hoặc riêng tư đã được cấp phép, ghi vào đường dẫn tạm, xử lý chuyển hướng có chủ ý, thất bại khi HTTP lỗi, có giới hạn dung lượng, lưu trạng thái và metadata phản hồi, kiểm tra loại hoặc nội dung tệp, và đối chiếu checksum khi có giá trị tin cậy.
Để đi tiếp trong Arcvenza, hãy xem /documentation để đọc tài liệu nền tảng, /quick-start-guides để làm theo hướng dẫn thiết lập và /tools/environment-check để kiểm tra môi trường trước khi tự động hóa.
