通过多部分请求上传文件
Upload file via multipart request
我需要将一个 zip 文件上传到 url,它接受在多部分请求中传递的文件。 "multipart/form-data" 请求中要绑定的部分的名称是 "archive"。
我目前拥有的:
auto f = new BufferedFile(<path_to_file>, FileMode.In);
scope (exit) f.close();
http = HTTP(<post_url>);
http.addRequestHeader("Content-Type", "multipart/form-data;boundary=heregoes");
http.verifyPeer(false);
http.method = HTTP.Method.post;
http.onSend = (void[] data){
return f.read(cast(ubyte[]) data);
};
http.contentLength = cast(size_t) f.size;
http.setCookieJar("<cookie_file_used_for_auth>");
http.perform();
如何在请求中设置键 "archive" 以将文件映射到?
谢谢
我不经常使用 std.net.curl 所以我不知道是否有更简单的方法,但您发送的数据只是网络上的一个 blob,因此您可以设置其他值手动。
不要只发送数据,将其放入 MIME 信封中。我不久前写了这个 class 来帮助形成:
/// Creates a multipart/form-data object that is suitable for file uploads and other kinds of POST
class FormData {
struct MimePart {
string name;
const(void)[] data;
string contentType;
string filename;
}
MimePart[] parts;
void append(string key, in void[] value, string contentType = null, string filename = null) {
parts ~= MimePart(key, value, contentType, filename);
}
private string boundary = "0016e64be86203dd36047610926a"; // FIXME
ubyte[] toBytes() {
string data;
foreach(part; parts) {
data ~= "--" ~ boundary ~ "\r\n";
data ~= "Content-Disposition: form-data; name=\""~part.name~"\"";
if(part.filename !is null)
data ~= "; filename=\""~part.filename~"\"";
data ~= "\r\n";
if(part.contentType !is null)
data ~= "Content-Type: " ~ part.contentType ~ "\r\n";
data ~= "\r\n";
data ~= cast(string) part.data;
data ~= "\r\n";
}
data ~= "--" ~ boundary ~ "--\r\n";
return cast(ubyte[]) data;
}
}
我知道代码很糟糕,我最近没有测试过它,但输出结果是正确的。它应该像这样工作:
auto data = new FormData();
data.append("archive", "YOUR DATA", "application/octet-stream"); // or whatever mime type you need
auto bytes = data.toBytes();
然后当 curl 要求时,您发送字节而不是文件内容。 HTTP
的setPostData
方法貌似是放的地方。请记住将设置 post 数据中的内容类型也设置为带有边界的 multipart/form-data(如果您愿意,可以更改我的 class 中的内容)。
http://dlang.org/phobos/std_net_curl.html#setPostData
我知道 curl 库也有为您执行此操作的函数...但我认为高级 std.net.curl 接口不会公开它们:(
我需要将一个 zip 文件上传到 url,它接受在多部分请求中传递的文件。 "multipart/form-data" 请求中要绑定的部分的名称是 "archive"。
我目前拥有的:
auto f = new BufferedFile(<path_to_file>, FileMode.In);
scope (exit) f.close();
http = HTTP(<post_url>);
http.addRequestHeader("Content-Type", "multipart/form-data;boundary=heregoes");
http.verifyPeer(false);
http.method = HTTP.Method.post;
http.onSend = (void[] data){
return f.read(cast(ubyte[]) data);
};
http.contentLength = cast(size_t) f.size;
http.setCookieJar("<cookie_file_used_for_auth>");
http.perform();
如何在请求中设置键 "archive" 以将文件映射到?
谢谢
我不经常使用 std.net.curl 所以我不知道是否有更简单的方法,但您发送的数据只是网络上的一个 blob,因此您可以设置其他值手动。
不要只发送数据,将其放入 MIME 信封中。我不久前写了这个 class 来帮助形成:
/// Creates a multipart/form-data object that is suitable for file uploads and other kinds of POST
class FormData {
struct MimePart {
string name;
const(void)[] data;
string contentType;
string filename;
}
MimePart[] parts;
void append(string key, in void[] value, string contentType = null, string filename = null) {
parts ~= MimePart(key, value, contentType, filename);
}
private string boundary = "0016e64be86203dd36047610926a"; // FIXME
ubyte[] toBytes() {
string data;
foreach(part; parts) {
data ~= "--" ~ boundary ~ "\r\n";
data ~= "Content-Disposition: form-data; name=\""~part.name~"\"";
if(part.filename !is null)
data ~= "; filename=\""~part.filename~"\"";
data ~= "\r\n";
if(part.contentType !is null)
data ~= "Content-Type: " ~ part.contentType ~ "\r\n";
data ~= "\r\n";
data ~= cast(string) part.data;
data ~= "\r\n";
}
data ~= "--" ~ boundary ~ "--\r\n";
return cast(ubyte[]) data;
}
}
我知道代码很糟糕,我最近没有测试过它,但输出结果是正确的。它应该像这样工作:
auto data = new FormData();
data.append("archive", "YOUR DATA", "application/octet-stream"); // or whatever mime type you need
auto bytes = data.toBytes();
然后当 curl 要求时,您发送字节而不是文件内容。 HTTP
的setPostData
方法貌似是放的地方。请记住将设置 post 数据中的内容类型也设置为带有边界的 multipart/form-data(如果您愿意,可以更改我的 class 中的内容)。
http://dlang.org/phobos/std_net_curl.html#setPostData
我知道 curl 库也有为您执行此操作的函数...但我认为高级 std.net.curl 接口不会公开它们:(