Каково значение Content-Type в HTTP-запросе при загрузке контента?

Мне нужно извлечь загрузки из http-trafic. Как это можно сделать? Прежде всего, запрос-метод будет POST. Во-вторых, будет поле заголовка Content-Type. Я не хочу извлекать данные формул, но загружаю их как почтовые вложения.

2 ответа

Решение

Тип контента соответствует спецификации multipart/form-data,

Это специальный тип контента, который можно визуализировать в виде нескольких подзапросов в одном большом запросе. Каждый из этих подзапросов (один элемент данных формы) имеет свой собственный набор заголовков. Тип содержимого фактических данных там.

Вот пример того, как это выглядит с 1 нормальным полем и 1 файловым полем (в терминах HTML, при использовании <input name="textfield"><input type="file" name="filefield">):

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() метод.

Если (и я ни в коем случае не говорю, что это правильный путь), вы просто хотите сохранить данные из байтового массива, вы должны посмотреть, как читать тело POST: Чтение тела POST с bottle.py Чтение данных, а затем Создание нового файла должно сделать свое дело.

На основе решения @BalusC я сделал небольшой метод расширения для сборки.NET в классе WebClient, который не поддерживает загрузку Multipart из коробки.

Применение

Просто смешайте строковые значения и файлы (заключенные в #)

    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);

    }
Другие вопросы по тегам