- 后端
【免费下载链接】transfer.sh
Easy and fast file sharing from the command-line.
本篇技术指南围绕 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 downloadsMax-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 的准备工作
- 登录 Storj 账户,进入 Access Grant 菜单,点击右上角 Wizard;
- 输入 access grant 名称,点击Next,按需做权限限制(也可在 CLI 或浏览器中继续);
- 设置一个用作加密密钥的 Passphrase——务必妥善保存,丢失后将永远无法解密你的文件;
- 复制生成的 access grant 即可启动 transfer.sh。
出于安全考虑,官方推荐将 access grant 与 bucket 名称都以环境变量方式提供:
export STORJ_BUCKET=<BUCKET NAME> export STORJ_ACCESS=<ACCESS GRANT> transfer.sh --provider storjStorj 存储实现在 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.logClamAV 病毒扫描(需配置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 查阅完整代码。
运维与安全要点
综合上文源码证据,自建实例时建议重点检查以下几点:
- IP 过滤:
ip-whitelist/ip-blacklist支持单个 IPv4/IPv6 或 CIDR 网段(如/24),Allowed优先于Blocked;但注意 README 顶部警告——X-Forwarded-For伪造可绕过,因此生产环境应在反向代理层做真实 IP 校验; - HTTP 基础认证:
http-auth-user/http-auth-pass或http-auth-htpasswd(htpasswd 文件,见 handlers.go 的 basicAuthHandler)对上传类路由生效,http-auth-ip-whitelist可让白名单 IP 免认证上传; - 限流与大小限制:
rate-limit(每分钟请求数,基于 IP 的 token bucket 中间件,见 server.go)与max-upload-size(KB,超出返回 413)可保护实例; - 自动清理:
purge-days+purge-interval(小时)启用后台定时清理(purgeHandler,不适用于 S3 与 Storj); - 健康检查:
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.
相关推荐
极速部署指南:打造专属transfer.sh文件分享服务
极速部署指南:打造专属transfer.sh文件分享服务 transfer.sh是一款简单高效的命令行文件分享工具,让你轻松实现文件的快速上传与分享。本指南将带
后端transfer.sh 命令行文件分享实战指南:上传下载、加密备份、病毒扫描与自动化脚本全解
transfer.sh 命令行文件分享实战指南:上传下载、加密备份、病毒扫描与自动化脚本全解 导读 本文以 transfer.sh 官方使用手册 example
后端transfer.sh:命令行下的简易快速文件共享指南
transfer.sh:命令行下的简易快速文件共享指南 项目介绍 transfer.sh 是一个开源项目,由 DutchCoders 开发并维护,它提供了一个简
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考