我需要从http-trafic中提取上传内容。怎么可能呢?首先,请求方法将是POST。其次,将有一个Content-Type标头字段。我不想提取公式数据,而是上传像邮件附件。
答案 0 :(得分:22)
内容类型为per specification multipart/form-data
。
这是一种特殊的内容类型,可以在一个大请求中显示为多个子请求。每个子请求(一个表单数据元素)都有自己的标题集。实际数据的内容类型就在那里。
以下是使用1个普通字段和1个文件字段(使用<input name="textfield"><input type="file" name="filefield">
时的HTML术语)的示例:
Content-Type: multipart/form-data;boundary=SOME_BOUNDARY
--SOME_BOUNDARY
content-disposition: form-data;name="textfield"
content-type: text/plain;charset=UTF-8
value of textfield here
--SOME_BOUNDARY
content-disposition: form-data;name="filefield";filename="some.ext"
content-type: application/octet-stream
binary file content here
--SOME_BOUNDARY--
至于解析和提取这些数据,实际上每种编程语言都有内置/第三方API。由于您没有说明您正在使用哪一个,因此无法给出有针对性的答案。在例如Java的情况下,这将是第三方库Apache Commons FileUpload,或者当您使用Servlet 3.0时,API提供的request.getPart()
方法。
答案 1 :(得分:0)
如果(我并不是说这是正确的方法)你只想保存字节数组中的数据,你应该看看如何在以下位置读取POST主体: Reading POST body with bottle.py 读取数据然后创建新文件应该可以解决问题。
答案 2 :(得分:0)
基于@BalusC的解决方案,我为WebClient类中的.NET构建提供了一些扩展方法,该方法不支持现成的分段上传。
只需混合字符串值和文件(用#括起来)
public void UploadMultipart()
{
var fileName = "/some/existing/file.ext";
using (var client = new WebClient())
{
var values = new NameValueCollection();
values.Add("id", Guid.NewGuid().ToString());
values.Add("name", Path.GetFileNameWithoutExtension(fileName));
values.Add("file", $"#{fileName}#");
var result = client.UploadMultipart(address, method, values);
var content = client.Encoding.GetString(result);
}
}
public static byte[] UploadMultipart(this WebClient client,
string address, string method, NameValueCollection values)
{
string boundary = DateTime.Now.Ticks.ToString("x");
client.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
var sb = new StringBuilder()
.AppendLine();
foreach (var key in values.AllKeys)
{
var contentDispositon = $"form-data;name=\"{key}\"";
var contentType = $"text/plain;charset={client.Encoding.WebName}";
var value = values[key];
if (value.StartsWith("#") && value.EndsWith("#"))
{
// if a value is enclosed in hashes we expect this to be a path to a file
// file=#/path/to/file.ext#
var fileName = value.Trim('#');
var file = File.ReadAllBytes(fileName);
value = client.Encoding.GetString(file);
contentType = "application/octet-stream";
contentDispositon = $"form-data;name=\"{key}\"filename=\"{Path.GetFileName(fileName)}\"";
}
sb.AppendLine($"--{boundary}")
.AppendLine($"Content-Disposition: {contentDispositon}")
.AppendLine($"Content-Type: {contentType}")
.AppendLine()
.AppendLine(value);
}
sb.AppendLine($"--{boundary}--");
var data = client.Encoding.GetBytes(sb.ToString());
return client.UploadData(address, method, data);
}