news 2026/10/3 2:30:19

transfer.sh 命令行文件分享服务器:从 curl 上传到自建部署的完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
transfer.sh 命令行文件分享服务器:从 curl 上传到自建部署的完整实战指南
  • 后端

【免费下载链接】transfer.sh

Easy and fast file sharing from the command-line.

项目地址:https://gitcode.com/gh_mirrors/tr/transfer.sh
点击查看免费下载

本篇技术指南围绕 transfer.sh 项目展开:这是一个用 Go 编写的、面向命令行的快速文件分享服务器,代码同时包含了可直接运行的服务端实现,让你既能使用公开实例完成"上传即得链接"的日常操作,也能在几分钟内自建私有实例。读完本文你将掌握完整的 curl/wget 上传下载流程、Max-Downloads / Max-Days 等请求头控制、服务端 AES256 加密与删除令牌机制、S3 / Google Drive / Storj / 本地文件系统四种存储后端配置,以及基于 Docker 与 Kubernetes 的部署方案。

项目概览与定位

transfer.sh 的核心目标只有一个:从命令行用最简单的方式完成文件分享。它提供的是一个完整的 HTTP 服务端,服务端接收PUT上传的任意文件,返回一个带随机 token 的短链接,任何人在有效期内通过该链接即可下载。当前代码库支持四种存储后端:

  • local:本地文件系统;
  • s3:Amazon S3 及兼容 S3 协议的对象存储;
  • gdrive:Google Drive;
  • storj:Storj 去中心化存储网络。

从 入口文件 可以看到,程序主体通过cmd.New()创建命令行应用并执行,所有能力都由 服务端核心 与 路由处理器 承载。

安全提醒:README 顶部明确标注了一个安全警告——IP 过滤器与 HTTP 认证存在通过未认证的X-Forwarded-For头伪造进行绕过的漏洞(详见项目 issue #670)。因此在公网部署时请务必结合防火墙、反向代理等外部手段加固,不要仅依赖内置的 IP 白名单做访问控制。

基础用法:上传、下载、加密与删除

上传文件

最简单的方式是使用 curl 的--upload-file参数,将本地文件直接推送到服务端:

$ curl -v --upload-file ./hello.txt https://transfer.sh/hello.txt

服务端返回一串 URL(包含随机 token 与文件名),例如https://transfer.sh/1lDau/hello.txt。从源码看,上传走的是 putHandler:文件名会经过sanitize()清洗(剥离控制字符、特殊 Unicode 分类并取path.Base),随后生成一个随机 token(长度由random-token-length决定,见 token.go 中基于 crypto/rand 种子实现的字符集生成器),文件本体与一个记录元数据的<filename>.metadata对象(JSON 格式,包含 ContentType、ContentLength、下载次数、MaxDownloads、MaxDate、DeletionToken 等字段)一起写入存储后端。

上传时加密(客户端侧 GPG)

如果希望文件在传输前即已加密,可先用 GPG 对称加密再上传:

$ gpg --armor --symmetric --output - /tmp/hello.txt | curl --upload-file - https://transfer.sh/test.txt

下载并解密

$ curl https://transfer.sh/1lDau/test.txt | gpg --decrypt --output /tmp/hello.txt

上传文件到 VirusTotal 扫描

在 URL 后追加/virustotal,服务端会把文件提交给 VirusTotal 并返回分析结果的 permalink:

$ curl -X PUT --upload-file nhgbhhj https://transfer.sh/test.txt/virustotal

该功能由 virustotal.go 中的virusTotalHandler实现,需要配置virustotal-key(VirusTotal API key)才能工作。

删除文件

每个文件在返回的响应头X-Url-Delete中带有唯一删除 URL,用DELETE方法请求该 URL 即可删除:

$ curl -X DELETE <X-Url-Delete Response Header URL>

删除的校验逻辑在 handlers.go 的 deleteHandler 与checkDeletionToken中:请求路径中的deletionToken必须与上传时生成并写入 metadata 的DeletionToken完全一致,否则返回 404。删除 token 是上传时由token(randomTokenLength) + token(randomTokenLength)拼接生成的(长度相当于两倍的上传路径 token),这也是为什么 README 中random-token-length参数注明"删除路径 token 是其两倍"。

请求头控制:下载次数、存活天数与服务端加密

这部分"请求头"是 transfer.sh 最具实用价值的能力,全部通过 curl 的-H参数附加。

Max-Downloads:限制下载次数

$ curl --upload-file ./hello.txt https://transfer.sh/hello.txt -H "Max-Downloads: 1" # Limit the number of downloads

Max-Days:设置自动过期天数

$ curl --upload-file ./hello.txt https://transfer.sh/hello.txt -H "Max-Days: 1" # Set the number of days before deletion

从 metadataForRequest 的实现可以看到:Max-Downloads被解析后写入 metadata 的MaxDownloads字段(默认 -1 表示不限);Max-Days被换算为time.Now().Add(time.Hour * 24 * v)存入MaxDate。每次下载时 checkMetadata 都会校验这两个条件——下载次数达到上限或过期都会返回错误,且下载计数会在持有 per-file 锁(lock(token, filename),基于sync.Map与sync.Mutex)的前提下递增并回写 metadata。与之配套,下载响应中还会返回X-Remaining-Downloads与X-Remaining-Days两个响应头,方便脚本感知剩余额度。

X-Encrypt-Password / X-Decrypt-Password:服务端 AES256 加密

$ curl --upload-file ./hello.txt https://your-transfersh-instance.tld/hello.txt -H "X-Encrypt-Password: test" # Encrypt the content server side with AES256 using "test" as password
$ curl https://your-transfersh-instance.tld/BAYh0/hello.txt -H "X-Decrypt-Password: test" # Decrypt the content server side with AES256 using "test" as password

重要警告(README 原文强调):请只在自建服务器上使用该功能——把文件交给第三方服务做服务端加密,信任风险完全由你自己承担。

实现上,加密/解密通过 OpenPGP 对称加密完成:attachEncryptionReader调用encrypt()(见 handlers.go),使用 AES256 密码套件(packet.CipherAES256)生成带 armor 包装的密文流;解密时attachDecryptionReader先armor.Decode解包,再以请求头携带的密码为 prompt 输入openpgp.ReadMessage,密码错误会触发"wrong password"错误。上传时若带X-Encrypt-Password,metadata 会记录Encrypted=true、原始 ContentType 存入DecryptedContentType、存储 ContentType 变为text/plain; charset=utf-8;下载时只有同时带对X-Decrypt-Password才能还原出原始内容类型与长度(见 getHandler)。

响应头:X-Url-Delete 与删除链接

每次上传成功后,服务端通过X-Url-Delete响应头返回删除专用 URL。用-D -(dump headers)即可看到:

curl -sD - --upload-file ./hello.txt https://transfer.sh/hello.txt | grep -i -E 'transfer\.sh|x-url-delete' x-url-delete: https://transfer.sh/hello.txt/BAYh0/hello.txt/PDw0NHPcqU https://transfer.sh/hello.txt/BAYh0/hello.txt

第一行是X-Url-Delete响应头(形如…/{token}/{filename}/{deletionToken}),第二行是普通下载链接。脚本可以通过解析该响应头自动构造删除命令——这正是后文"带删除链接的高级 Shell 函数"的基础。

链接别名:强制下载与内联预览

对于任意形如https://transfer.sh/{token}/{filename}的下载链接,可以在 token 前插入动作前缀获得两种行为:

  • 直接下载(get 别名):https://transfer.sh/1lDau/test.txt→https://transfer.sh/get/1lDau/test.txt;
  • 内联预览(inline 别名):https://transfer.sh/1lDau/test.txt→https://transfer.sh/inline/1lDau/test.txt。

路由层面由 server.go 的/{action:(?:download|get|inline)}/{token}/{filename}模式承载,getHandler中根据action决定Content-Disposition是attachment还是inline;inline 模式下若无法判定内容类型会回退为text/plain; charset=utf-8以防 XSS,并会对可嵌入 HTML 的内容类型(如 html、xml、vtt、xsl 等,见canContainsXSS)做 bluemonday 的 UGC 策略净化。此外浏览器直接访问普通链接时,previewHandler 会根据 Accept 头与 Referer 判断是否渲染预览页(图片/视频/音频/文本/markdown 各有模板,还附带二维码)。

自建部署:参数表与两种 HTTPS 方案

全部运行参数

下表完整列出服务端支持的全部命令行参数、取值与对应环境变量(环境变量与 flag 等价,均可使用;源码定义见 cmd/cmd.go):

| 参数 | 说明 | 默认值 | 环境变量 | |--- |---|---|--| | listener | http 监听地址(如 127.0.0.1:8080) | 127.0.0.1:8080 | LISTENER | | profile-listener | profiler 监听地址(默认 :6060) | | PROFILE_LISTENER | | force-https | 强制跳转 https | false | FORCE_HTTPS | | tls-listener | https 监听端口(:443) | | TLS_LISTENER | | tls-listener-only | 仅启用 tls 监听 | | TLS_LISTENER_ONLY | | tls-cert-file | TLS 证书路径 | | TLS_CERT_FILE | | tls-private-key | TLS 私钥路径 | | TLS_PRIVATE_KEY | | http-auth-user | 上传的 basic http auth 用户名 | | HTTP_AUTH_USER | | http-auth-pass | 上传的 basic http auth 密码 | | HTTP_AUTH_PASS | | http-auth-htpasswd | basic http auth 的 htpasswd 文件路径 | | HTTP_AUTH_HTPASSWD | | http-auth-ip-whitelist | 免认证上传的 IP 白名单(逗号分隔) | | HTTP_AUTH_IP_WHITELIST | | virustotal-key | VirusTotal API key | | VIRUSTOTAL_KEY | | ip-whitelist | 允许连接服务的 IP 列表(逗号分隔) | | IP_WHITELIST | | ip-blacklist | 禁止连接服务的 IP 列表(逗号分隔) | | IP_BLACKLIST | | temp-path | 临时目录 | 系统临时目录 | TEMP_PATH | | web-path | 静态前端文件路径(开发或自定义前端) | | WEB_PATH | | proxy-path | 反向代理路径前缀(开头的/会被修剪) | | PROXY_PATH | | proxy-port | 反向代理的端口 | | PROXY_PORT | | email-contact | 前端"联系我们"邮箱 | | EMAIL_CONTACT | | ga-key | 前端 Google Analytics key | | GA_KEY | | provider | 存储提供商 | | PROVIDER | | uservoice-key | 前端 UserVoice key | | USERVOICE_KEY | | aws-access-key | AWS access key | | AWS_ACCESS_KEY | | aws-secret-key | AWS secret key | | AWS_SECRET_KEY | | bucket | AWS bucket | | BUCKET | | s3-endpoint | 自定义 S3 endpoint | | S3_ENDPOINT | | s3-region | S3 bucket 区域 | eu-west-1 | S3_REGION | | s3-credentials-type | S3 凭证模式(legacy或default-sdk-credential-chain) | legacy | S3_CREDENTIALS_TYPE | | s3-no-multipart | 禁用 S3 分片上传 | false | S3_NO_MULTIPART | | s3-path-style | 强制 path-style URL(Minio 必需) | false | S3_PATH_STYLE | | storj-access | Storj 项目的 Access Grant | | STORJ_ACCESS | | storj-bucket | Storj 项目中的 bucket | | STORJ_BUCKET | | basedir | local/gdrive 提供商的存储路径 | | BASEDIR | | gdrive-client-json-filepath | gdrive 的 OAuth client json 配置路径 | | GDRIVE_CLIENT_JSON_FILEPATH | | gdrive-local-config-path | gdrive 本地配置缓存目录 | | GDRIVE_LOCAL_CONFIG_PATH | | gdrive-chunk-size | gdrive 上传分片大小(MB,需低于可用内存,默认 8 MB) | 8 | GDRIVE_CHUNK_SIZE | | lets-encrypt-hosts | 使用 Let's Encrypt 的主机名(逗号分隔) | | HOSTS | | log | 日志文件路径 | | LOG | | cors-domains | 允许 CORS 的域名列表(逗号分隔,设置即启用 CORS) | | CORS_DOMAINS | | clamav-host | ClamAV 功能的主机 | | CLAMAV_HOST | | perform-clamav-prescan | 上传前用 ClamAV 预扫描(clamav-host 必须是本地 clamd unix socket) | | PERFORM_CLAMAV_PRESCAN | | rate-limit | 每分钟请求数 | | RATE_LIMIT | | max-upload-size | 最大上传大小(KB) | | MAX_UPLOAD_SIZE | | purge-days | 上传多少天后自动清理 | | PURGE_DAYS | | purge-interval | 自动清理运行间隔(小时,不适用于 S3 与 Storj) | | PURGE_INTERVAL | | random-token-length | 上传路径随机 token 长度(删除路径为其两倍) | 6(源码默认 10) | RANDOM_TOKEN_LENGTH |

注意:README 参数表中listener默认标注为 :80、random-token-length默认标注为 6,而当前仓库源码 cmd.go 中listener的默认值是127.0.0.1:8080、random-token-length默认值为 10,以源码为准。

使用 Let's Encrypt 自动证书

若要用 Let's Encrypt 自动签发证书,配置三个参数即可:

# 设置 lets-encrypt-hosts 为你的域名,tls-listener 为 :443,并启用 force-https transfer.sh --provider local --basedir /tmp/ --lets-encrypt-hosts example.com --tls-listener :443 --force-https

实现上通过 UseLetsEncrypt 创建autocert.Manager(证书缓存在./cache/目录,HostPolicy校验请求主机必须是所配域名或其子域)。

使用自有证书

# 设置 tls-listener 为 :443,同时给出 force-https、tls-cert-file 与 tls-private-key transfer.sh --provider local --basedir /tmp/ --tls-listener :443 --force-https --tls-cert-file /path/cert.pem --tls-private-key /path/key.pem

自有证书路径由 TLSConfig 通过tls.LoadX509KeyPair加载,并作为GetCertificate回调使用。若只想用tls-listener-only则纯 TLS 监听、不启动 HTTP。

本地开发与手动构建

项目使用 Go Modules(GO111MODULE),本地一条命令即可把服务跑起来(local 提供商 + 8080 端口):

go run main.go --provider=local --listener :8080 --temp-path=/tmp/ --basedir=/tmp/

源码构建(产物为transfersh可执行文件):

$ git clone git@github.com:dutchcoders/transfer.sh.git $ cd transfer.sh $ go build -o transfersh main.go

如需查看版本信息,transfer.sh version子命令会输出类似transfer.sh 0.0.0: Easy file sharing from the command line的内容(版本号通过构建参数注入,见 cmd.go)。

Docker 部署

官方提供 Docker 镜像,方便快速部署。镜像分两种变体,区别仅在于以哪个用户运行进程。

默认(root 用户)镜像

docker run --publish 8080:8080 dutchcoders/transfer.sh:latest --provider local --basedir /tmp/

[!WARNING] 官方不建议 WatchTower 之类的工具使用latest标签:latest可能指向未发布的开发版、测试构建或旧版本补丁。请使用具体版本标签,直到 transfer.sh 开始提供 major/minor 版本标签。

最小权限镜像(推荐)

以-noroot为后缀的镜像以最小权限运行(UID/GID 均为 5000),降低应用被攻破后的攻击面。官方 README 明确建议优先使用-noroot:

docker run --publish 8080:8080 dutchcoders/transfer.sh:latest-noroot --provider local --basedir /tmp/

镜像标签

| 标签 | 用途 | |--|--| | latest | 最新 CI 构建(可能是 nightly、commit 或 tag 构建) | | latest-noroot | 同上,但使用非 root 用户 | | nightly | 每天 UTC 午夜定时 CI 构建 | | nightly-noroot | 同上,但使用非 root 用户 | | edge |main分支每次提交后的最新 CI 构建 | | edge-noroot | 同上,但使用非 root 用户 | | vx.y.z| 打 tag 发布后的 CI 构建 | | vx.y.z-noroot | 同上,但使用非 root 用户 |

自定义构建容器(自选 UID/GID)

如果使用 NFS 挂载等场景需要自定义 UID/GID,可以自行构建:

# 构建参数: # * RUNAS: 为空则容器以 root 运行;设置任意值则启用 UID/GID 选择。 # * PUID: 进程 UID,需 RUNAS 非空,默认 5000。 # * PGID: 进程 GID,需 RUNAS 非空,默认 5000。 docker build -t transfer.sh-noroot --build-arg RUNAS=doesntmatter --build-arg PUID=1337 --build-arg PGID=1338 .

从仓库 Dockerfile 可以看到镜像采用多阶段构建:golang:alpine中编译(CGO_ENABLED=0静态链接、注入cmd.Version),最终产物复制进scratch基础镜像,RUNAS非空时会生成对应的/etc/passwd、/etc/shadow、/etc/group条目以实现非 root 运行。项目也提供了 Kubernetes 部署清单(Helm chart 位于 k8s/transfer.sh),包含 deployment、hpa、ingress、networkpolicy、pvc 等模板,可作为生产环境编排参考。

存储后端配置

S3(Amazon S3 与自定义兼容服务)

使用 AWS S3 bucket 只需指定以下选项(均支持 flag 或环境变量二选一):

  • --provider s3
  • --aws-access-key(或环境变量AWS_ACCESS_KEY)
  • --aws-secret-key(或环境变量AWS_SECRET_KEY)
  • --bucket(或环境变量BUCKET)
  • --s3-region(或环境变量S3_REGION)

凭证模式说明:

  • 默认legacy模式要求同时提供静态的 access key 与 secret key;
  • 显式设置--s3-credentials-type default-sdk-credential-chain(或环境变量S3_CREDENTIALS_TYPE=default-sdk-credential-chain)则改用 AWS SDK 默认凭证链,支持环境凭证、共享 AWS 配置文件、ECS 任务角色、EC2 实例配置文件以及 EKS IRSA 等来源。

指定s3-region后无需再设置 endpoint,SDK 会自动选择正确 endpoint。

自定义 S3 提供商

使用非 AWS 的 S3 兼容存储(如 MinIO)时,需要按云厂商文档指定s3-endpoint;同时若服务要求 path-style URL(MinIO 即如此),需开启--s3-path-style。其余常用组合:--s3-no-multipart可禁用 S3 分片上传。S3 存储实现见 s3.go,其配套测试位于 s3_test.go。

Storj 去中心化存储

使用 Storj Network 作为存储后端需要指定:

  • --provider storj
  • --storj-access(或环境变量STORJ_ACCESS)
  • --storj-bucket(或环境变量STORJ_BUCKET)
创建 Bucket 与 Access Grant 的准备工作
  1. 登录 Storj 账户,进入 Access Grant 菜单,点击右上角 Wizard;
  2. 输入 access grant 名称,点击Next,按需做权限限制(也可在 CLI 或浏览器中继续);
  3. 设置一个用作加密密钥的 Passphrase——务必妥善保存,丢失后将永远无法解密你的文件;
  4. 复制生成的 access grant 即可启动 transfer.sh。

出于安全考虑,官方推荐将 access grant 与 bucket 名称都以环境变量方式提供:

export STORJ_BUCKET=<BUCKET NAME> export STORJ_ACCESS=<ACCESS GRANT> transfer.sh --provider storj

Storj 存储实现在 storj.go。

Google Drive

使用 Google Drive 需要指定:

  • --provider gdrive
  • --gdrive-client-json-filepath
  • --gdrive-local-config-path
  • --basedir
创建 Gdrive Client Json

在 console.cloud.google.com 创建一个 OAuth Client ID,下载 JSON 文件并放置到安全目录。

启动示例
go run main.go --provider gdrive --basedir /tmp/ --gdrive-client-json-filepath /[credential_dir] --gdrive-local-config-path [directory_to_save_config]

gdrive-chunk-size控制上传分片大小(MB,默认取 Google API 默认分片大小换算值,即 8 MB),需低于可用内存。GDrive 存储实现在 gdrive.go。

Shell 函数:把文件分享变成一条命令

简易版(Bash / ash / zsh,多文件打包为 zip)

将以下函数加入.bashrc、.zshrc或等价配置:

transfer() (if [ $# -eq 0 ]; then printf "No arguments specified.\nUsage:\n transfer <file|directory>\n ... | transfer <file_name>\n">&2; return 1; fi; file_name=$(basename "$1"); if [ -t 0 ]; then file="$1"; if [ ! -e "$file" ]; then echo "$file: No such file or directory">&2; return 1; fi; if [ -d "$file" ]; then cd "$file" || return 1; file_name="$file_name.zip"; set -- zip -r -q - .; else set -- cat "$file"; fi; else set -- cat; fi; url=$("$@" | curl --silent --show-error --progress-bar --upload-file "-" "https://transfer.sh/$file_name"); echo "$url"; )

之后即可直接使用:

$ transfer hello.txt

该函数会智能判断输入:目录被自动zip -r打包后上传(文件名追加.zip),普通文件直接上传,来自管道的 stdin 则以指定文件名上传。

进阶版(Bash / zsh:输出删除命令、删除 token,上传前二次确认)

展开查看完整函数
transfer() { local file declare -a file_array file_array=("${@}") if [[ "${file_array[@]}" == "" || "${1}" == "--help" || "${1}" == "-h" ]] then echo "${0} - Upload arbitrary files to \"transfer.sh\"." echo "" echo "Usage: ${0} [options] [<file>]..." echo "" echo "OPTIONS:" echo " -h, --help" echo " show this message" echo "" echo "EXAMPLES:" echo " Upload a single file from the current working directory:" echo " ${0} \"image.img\"" echo "" echo " Upload multiple files from the current working directory:" echo " ${0} \"image.img\" \"image2.img\"" echo "" echo " Upload a file from a different directory:" echo " ${0} \"/tmp/some_file\"" echo "" echo " Upload all files from the current working directory. Be aware of the webserver's rate limiting!:" echo " ${0} *" echo "" echo " Upload a single file from the current working directory and filter out the delete token and download link:" echo " ${0} \"image.img\" | awk --field-separator=\": \" '/Delete token:/ { print \$2 } /Download link:/ { print \$2 }'" echo "" echo " Show help text from \"transfer.sh\":" echo " curl --request GET \"https://transfer.sh\"" return 0 else for file in "${file_array[@]}" do if [[ ! -f "${file}" ]] then echo -e "\e[01;31m'${file}' could not be found or is not a file.\e[0m" >&2 return 1 fi done unset file fi local upload_files local curl_output local awk_output du -c -k -L "${file_array[@]}" >&2 # be compatible with "bash" if [[ "${ZSH_NAME}" == "zsh" ]] then read $'upload_files?\e[01;31mDo you really want to upload the above files ('"${#file_array[@]}"$') to \"transfer.sh\"? (Y/n): \e[0m' elif [[ "${BASH}" == *"bash"* ]] then read -p $'\e[01;31mDo you really want to upload the above files ('"${#file_array[@]}"$') to \"transfer.sh\"? (Y/n): \e[0m' upload_files fi case "${upload_files:-y}" in "y"|"Y") # for the sake of the progress bar, execute "curl" for each file. # the parameters "--include" and "--form" will suppress the progress bar. for file in "${file_array[@]}" do # show delete link and filter out the delete token from the response header after upload. # it is important to save "curl's" "stdout" via a subshell to a variable or redirect it to another command, # which just redirects to "stdout" in order to have a sane output afterwards. # the progress bar is redirected to "stderr" and is only displayed, # if "stdout" is redirected to something; e.g. ">/dev/null", "tee /dev/null" or "| <some_command>". # the response header is redirected to "stdout", so redirecting "stdout" to "/dev/null" does not make any sense. # redirecting "curl's" "stderr" to "stdout" ("2>&1") will suppress the progress bar. curl_output=$(curl --request PUT --progress-bar --dump-header - --upload-file "${file}" "https://transfer.sh/") awk_output=$(awk \ 'gsub("\r", "", $0) && tolower($1) ~ /x-url-delete/ \ { delete_link=$2; print "Delete command: curl --request DELETE " "\""delete_link"\""; gsub(".*/", "", delete_link); delete_token=delete_link; print "Delete token: " delete_token; } END{ print "Download link: " $0; }' <<< "${curl_output}") # return the results via "stdout", "awk" does not do this for some reason. echo -e "${awk_output}\n" # avoid rate limiting as much as possible; nginx: too many requests. if (( ${#file_array[@]} > 4 )) then sleep 5 fi done ;; "n"|"N") return 1 ;; *) echo -e "\e[01;31mWrong input: '${upload_files}'.\e[0m" >&2 return 1 esac }

该函数逐文件用curl --request PUT --progress-bar --dump-header - --upload-file上传,再用 awk 从响应头中提取x-url-delete,同时打印出可直接复制的删除命令、删除 token 与下载链接;超过 4 个文件时每次间隔 5 秒,以规避nginx: too many requests限流。

示例输出
$ ls -lh total 20M -rw-r--r-- 1 <some_username> <some_username> 10M Apr 4 21:08 image.img -rw-r--r-- 1 <some_username> <some_username> 10M Apr 4 21:08 image2.img $ transfer image* 10240K image2.img 10240K image.img 20480K total Do you really want to upload the above files (2) to "transfer.sh"? (Y/n): ######################################################################################################################################################################################################################################## 100.0% Delete command: curl --request DELETE "https://transfer.sh/wJw9pz/image2.img/mSctGx7pYCId" Delete token: mSctGx7pYCId Download link: https://transfer.sh/wJw9pz/image2.img ######################################################################################################################################################################################################################################## 100.0% Delete command: curl --request DELETE "https://transfer.sh/ljJc5I/image.img/nw7qaoiKUwCU" Delete token: nw7qaoiKUwCU Download link: https://transfer.sh/ljJc5I/image.img $ transfer "image.img" | awk --field-separator=": " '/Delete token:/ { print $2 } /Download link:/ { print $2 }' 10240K image.img 10240K total Do you really want to upload the above files (1) to "transfer.sh"? (Y/n): ######################################################################################################################################################################################################################################## 100.0% tauN5dE3fWJe https://transfer.sh/MYkuqn/image.img

更多实战组合:备份、归档与自动化

仓库 examples.md 提供了大量可直接套用的实战场景,这里摘录几类最常用的:

备份 MySQL 并加密上传

$ mysqldump --all-databases | gzip | gpg -ac -o- | curl -X PUT --upload-file "-" https://transfer.sh/test.txt

归档目录并上传

$ tar -czf - /var/log/journal | curl --upload-file - https://transfer.sh/journal.tar.gz

一次上传多个文件(multipart 表单)

$ curl -i -F filedata=@/tmp/hello.txt -F filedata=@/tmp/hello2.txt https://transfer.sh/

一次性下载多个文件并打包为 zip / tar.gz(逗号分隔多个{token}/{filename})

$ curl https://transfer.sh/(15HKz/hello.txt,15HKz/hello.txt).tar.gz $ curl https://transfer.sh/(15HKz/hello.txt,15HKz/hello.txt).zip

该能力由 server.go 的zipHandler/tarHandler/tarGzHandler实现(见 handlers.go),服务端流式打包,zip 使用 Store 模式(不压缩),tar/tar.gz 则顺序写出。

用 wget 上传

$ wget --method PUT --body-file=/tmp/file.tar https://transfer.sh/file.tar -O - -nv

上传过滤后的文本

$ grep 'pound' /var/log/syslog | curl --upload-file - https://transfer.sh/pound.log

ClamAV 病毒扫描(需配置clamav-host,上传到/scan端点)

$ wget http://www.eicar.org/download/eicar.com $ curl -X PUT --upload-file ./eicar.com https://transfer.sh/eicar.com/scan

加密 + 限制下载次数的传输函数(transfer-encrypted -D 50 %file%,默认限制 1 次下载)

$ curl -s https://transfer.sh/some/file | openssl aes-256-cbc -pbkdf2 -d > output_filename

此外 examples.md 还包含 fish-shell 的transfer函数、Windowstransfer.cmd(PowerShell PUT 上传)、以及"上传后自动把 Linux/macOS/Windows 下载命令复制到剪贴板"的transfer变体(依赖 xclip/xsel 或 macOS 自带的 pbcopy/pbpaste),可前往 examples.md 查阅完整代码。

运维与安全要点

综合上文源码证据,自建实例时建议重点检查以下几点:

  1. IP 过滤:ip-whitelist/ip-blacklist支持单个 IPv4/IPv6 或 CIDR 网段(如/24),Allowed优先于Blocked;但注意 README 顶部警告——X-Forwarded-For伪造可绕过,因此生产环境应在反向代理层做真实 IP 校验;
  2. HTTP 基础认证:http-auth-user/http-auth-pass或http-auth-htpasswd(htpasswd 文件,见 handlers.go 的 basicAuthHandler)对上传类路由生效,http-auth-ip-whitelist可让白名单 IP 免认证上传;
  3. 限流与大小限制:rate-limit(每分钟请求数,基于 IP 的 token bucket 中间件,见 server.go)与max-upload-size(KB,超出返回 413)可保护实例;
  4. 自动清理:purge-days+purge-interval(小时)启用后台定时清理(purgeHandler,不适用于 S3 与 Storj);
  5. 健康检查:GET /health.html返回固定文本,可用于负载均衡探活(force-https开启时该路径不会被重定向)。

许可证与维护

本项目代码与文档遵循 MIT 许可(见 LICENSE),版权归属 Remco Verhoef(2011-2018)与 Andrea Spacca(2018-2020)、Andrea Spacca 与 Stefan Benten(2020 至今)。当前维护者为 Andrea Spacca 与 Stefan Benten。官方立场明确:如需长期使用,请自行托管实例;仓库不会为任何第三方公共实例做宣传。

  • 后端

【免费下载链接】transfer.sh

Easy and fast file sharing from the command-line.

项目地址:https://gitcode.com/gh_mirrors/tr/transfer.sh
点击查看免费下载
上一篇:CANN ops-math 非连续 Tensor 完全指南:基于 (shape, strides, offset) 的视图表示与内存寻址
下一篇:Security-101 第 1.3 课深度解读:理解风险管理——从核心术语到风险评估的完整框架

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 2:29:51

AI Agent_7 AI 提示词工程(Prompt Engineering)

一、先建立直觉&#xff1a;提示词是什么提示词&#xff08;Prompt&#xff09; 你输入给大模型的那段文本&#xff08;指令、问题、背景、示例&#xff09;。 提示词工程 有方法地设计这段文本&#xff0c;让模型稳定输出你想要的结果。示例&#xff1a;同一个任务&#xff…

作者头像 李华
网站建设 2026/10/3 2:29:01

DJI Mimo 只能单条色彩还原导出太痛苦?试试这样批量还原 D-LogM

# 前言&#xff1a;一条被忽略的痛点 用 DJI 运动相机&#xff08;Osmo Action / Pocket 系列&#xff09;拍运动视频的人都知道&#xff1a;用 D-Log / D-LogM 模式拍出来的画面是「灰片」——低饱和、低对比&#xff0c;直接看毫无电影感。因为它们保留了大范围的动态范围和…

作者头像 李华
网站建设 2026/10/3 2:28:00

6款开源轻量级服务器监控工具合集,可Docker一键部署!

6款开源轻量级服务器监控工具合集&#xff0c;可Docker一键部署&#xff01;前言一、ServerBee1.1 ServerBee简介1.2 ServerBee主要特点1.3 项目地址1.4 项目预览二、CheckCle2.1 CheckCle简介2.2 CheckCle主要特性1.3 项目地址2.4 项目预览三、Checkmate介绍3.1 Checkmate简介…

作者头像 李华
网站建设 2026/10/3 2:27:14

《30分钟从零到智能体》:与 Max Johnson 一起搭建内容引擎

《30分钟从零到智能体》&#xff1a;与 Max Johnson 一起搭建内容引擎 把重复性的内容创作工作&#xff0c;变成一条自动化的工作流 人工智能机构 briix 的创始人 Max Johnson&#xff0c;长期为企业主和创始人发布实用的 AI 使用指南&#xff0c;帮助他们更高效地利用人工智能…

作者头像 李华