我试图在Crystal中构建一个CLI工具,以便从命令行使用send-anywhere.com
。
发送multipart不是内置在Crystal中,但在编写我自己之前我想我会尝试使用cURL来查看我应该如何制作它但我甚至无法使用cURL!
问题在于,当使用cURL发送多个文件时,他们的服务器只看到1个文件传入,他们确实看到了总长度,但失败了50%,因为他们只期待一个文件。 / p>
让我失望的是它在浏览器中工作,我打开了网络检查器,但是我没有看到与我的cURL请求的区别。 我已经尝试将Expect标头设置为100-continue,我已经对它们进行了比较但是我没有看到什么能使它与浏览器一起工作而不是卷曲。
这是我用cURL尝试的命令都具有相同的结果,服务器最终只看到1个文件传入而不是2。
出于测试目的,我使用了一些通用LICENSE文件的副本。
curl -F file1=@LICENSE -F file2=@LICENSE1 https://...their.weblink...
我在检查员中看到Chrome在Content-Disposition中命名文件名=“file []”,所以我自己尝试了(同样的结果):
curl -F file[]=@LICENSE -F file[]=@LICENSE1 https://...their.weblink...
我也使用-H "Expect: 100-continue"
尝试了这两个命令,结果相同。
此时我生气了,以为我会自己尝试一下,也许cURL不能正确地做到这一点(非常不可能的imo,我做错事的可能性要大得多)。
因此,在从头开始编写之前,我尝试了Telegram bot使用的实现,请参阅此处:https://github.com/hangyas/TelegramBot/blob/b3fcbbb621bd669bbafe9f3e91364702d06d1e10/src/TelegramBot/http_client_multipart.cr
这很简单,但我仍然遇到同样的问题。只识别第一个文件。
注意:当只发送一个文件时,一切都适用于cURL和Crystal实现。
我要发疯了,有效的浏览器和其他两个有什么区别?我没看到什么?
我不是在寻找一个实现,只是为了让某人指出我错过了什么会使多个文件被正确识别?
答案 0 :(得分:2)
这仅用于教育目的,实际上这样做违反了 服务条款。它有一个您应该使用的文档API 相反,在给出API密钥之后。
正确公布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"