无法使用 curl 将多个文件发送到 send-anywhere.com

Failing to send multiple files with curl to send-anywhere.com

我试图在 Crystal 中构建一个 CLI 工具以从命令行使用 send-anywhere.com

发送多部分不是 Crystal 内置的,但在编写我自己的之前,我想我会尝试使用 cURL 来查看我应该如何制作它,但我什至无法让它与 cURL 一起工作!

问题是,当使用 cURL 发送 多个文件 时,他们的服务器只看到 1 个传入的文件,他们确实看到了总长度,但在 50% 时失败,因为它们只是期待一个文件。

令我恼火的是它在浏览器中运行,我打开了网络检查器,但我看不出与我的 cURL 请求有什么不同。 我试过将 Expect header 设置为 100-continue,我比较了它们,但我看不出是什么让它可以与浏览器一起工作而不是 curl。

这是我用 cURL 尝试的命令,所有结果都相同,服务器最终只看到 1 个传入文件,而不是 2 个。

出于测试目的,我使用了几个通用许可文件的副本。

curl -F file1=@LICENSE -F file2=@LICENSE1 https://...their.weblink...

我在inspector中看到Chrome在Content-Disposition中命名文件name="file[]",所以我自己试了一下(结果一样):

curl -F file[]=@LICENSE -F file[]=@LICENSE1 https://...their.weblink...

我也使用 -H "Expect: 100-continue" 尝试了这 2 个命令,结果相同。

在这一点上我很生气,我想我会自己尝试一下,也许 cURL 不能正确地做到这一点(imo 极不可能,我做错事的可能性更高)。

所以在从头开始编写之前,我尝试了一个 Telegram 机器人使用的实现,请参见此处:https://github.com/hangyas/TelegramBot/blob/b3fcbbb621bd669bbafe9f3e91364702d06d1e10/src/TelegramBot/http_client_multipart.cr

这很简单,但我仍然遇到同样的问题。只识别第一个文件。

注意:当只发送一个文件时,cURL 和 Crystal 实现一切正常。

我快疯了,能用的浏览器和其他两个有什么区别?我没看到什么?

我不是在寻找实现,只是希望有人指出我遗漏的内容,以便正确识别多个文件?

This is for educational purposes only, actually doing this violates the terms of service. It has a documented API you should use instead, after given an API key.

正确地向 key 端点公布文件数量很重要。所以整个流程是这样的:

#!/bin/bash

# First we need to get a device key by registering ourselves as a
# device. For that we need a profile name. We need to store the
# received cookie and send it with the subsequent request.
profilename="$(openssl rand -hex 6)"
curl -c .session -vL https://send-anywhere.com/web/device \
  -d "os_type=web" \
  -d "profile_name=$profilename" \
  -d "manufacturer=Linux" \
  -d "model_number=Firefox" \
  -d "app_version=48" \
  -d "device_language=en-US"

# We need to know the individual filesizes in bytes as well as
# the total size we're going to upload
file0name="foo.txt"
file0size="$(wc -c "$file0name" | cut -d ' ' -f 1)"
file1name="bar.txt"
file1size="$(wc -c "$file1name" | cut -d ' ' -f 1)"
filesize="$(echo "$file0size + $file1size" | bc)"

# Using that info and the cookie we got from the device key
# we can correctly announce our upload
key="$(curl -b .session -vL https://send-anywhere.com/web/key \
  -d "file[0][name]=$file0name" -d "file[0][size]=$file0size" \
  -d "file[1][name]=$file1name" -d "file[1][size]=$file1size" \
  -d "file_number=2" -d "file_size=$filesize")"

# We get some JSON back with the URL to send to the receiver
# and the URL to upload back
url="$(echo "$key" | ruby -rjson -e 'print JSON.parse($stdin.read)["link"]')"
upload_url="$(echo "$key" | ruby -rjson -e 'print JSON.parse($stdin.read)["weblink"]')"

echo
echo "------------------------------------------------------------"
echo "Receive 2 files of $filesize bytes at $url"
echo "------------------------------------------------------------"
echo

# And finally do the upload
curl -vL "$upload_url" \
  -F "file[]=@$file0name" \
  -F "file[]=@$file1name"