Привет, геи, вы делаете Content-Disposition?

внешний интерфейс HTTP

задний план

Во второй половине рабочего дня ко мне подошел фронтенд-друг и сказал: "Моя онлайн-страница оказалась в порядке. Почему она стала загружаемой, когда я зашел сегодня? Я ничего не делал?" В этот момент некоторые люди также сообщили, что все веб-страницы были загружены при доступе к ним.

После срочного расследования было установлено, что причиной проблемы стал некий Alibaba CloudCDNВозникла проблема со сборкой запроса возврата узла к источнику, в результате чегоOSSПроисхождение не может быть признаноCDNзапросить и вставитьcontent-dispositionзаголовок, который в конечном итоге влияет на логику обработки файла браузером. (Он должен быть отображен браузером и загружен как вложение).

Итак, о чем я хочу поговорить с вами сегодня, так это о том, что вызвало эту онлайн-проблему.Content-dispositionКак это свято.

Content-Disposition

Content-DispositionЕсть два сценария применения.

Используется в заголовках ответов HTTP

Сценарий 1 используется в заголовках ответов HTTP, чтобы указать, как должно отображаться содержимое ответа. Будь то встроенная форма (то есть веб-страница или часть страницы) или загруженная и сохраненная локально в виде вложения.

Content-DispositionПервый параметр имеет два значения:

  • inlineЗначение по умолчанию, означающее, что тело сообщения в ответе отображается как часть страницы или как вся страница.
  • attachmentТело сообщения, представляющее ответ, должно быть загружено локально; большинство браузеров отобразит диалоговое окно «сохранить как».

Второй параметр является необязательнымfilename.当响应的内第一个参数指定为attachment, браузер загрузит содержимое ответа,filenameМожно указать имя загруженного файла.

Content-DispositionВ заголовках ответов это может выглядеть так:

// 正常解析渲染
Content-Disposition: inline
// 下载文件
Content-Disposition: attachment
// 下载文件,并将文件保存为filename.jpg
Content-Disposition: attachment; filename="filename.jpg"

Используется в теле запроса multipart/form-data

Другой сценарий заключается в том, что когда на странице есть форма, и метод отправки формы, который мы выбираем,multipart/form-dataчас,Content-DispositionОн появится в теле запроса. Его роль заключается в том, чтобы проиллюстрировать, какое имя поля соответствующей формы, какое имя файла, загруженного в форму. Первый параметр в этой сцене всегда фиксирован.form-data, с двумя дополнительными необязательными параметрами.nameУказывает имя поля соответствующего элемента формы,filenameУказывает имя соответствующего загруженного файла. использовать между параметрами;разделять.

Content-Dispositionсуществуетmultipart/form-dataЗаголовок тела запроса может выглядеть следующим образом:

Content-Disposition: form-data
Content-Disposition: form-data; name="fieldName"
Content-Disposition: form-data; name="fieldName"; filename="filename.jpg"

Пример

Далее, давайте углубим наше впечатление об этом на примере. Этот пример в основном демонстрирует две части функции.

  • установивContent-Disposition: attachmentЗагрузите файл, который сохраняет запрос в вашем браузере.
  • Проиллюстрируйте, реализуя почтовый запросContent-Disposition: form-dataФорма представления в теле запроса.

СоздайтеcontentDispositionDemoкаталог, выполнить:

npm install express multiparty

Код сервера, который мы используемexpressдобиться, используяmultipartyмодуль для обработкиmultipart/form-dataзапрос. Код сервера выглядит следующим образом:

// app.js
const express = require("express");
const multiparty = require("multiparty");
const app = express();
const port = 3000;
app.use(express.static("public"));

// 访问的时候,弹窗提示下载attachment.html,并保存为ddd.html
app.get("/attach", (req, res, next) => {
  const options = {
    root: __dirname,
    headers: {
      "Content-Disposition": "attachment;filename=ddd.html"
    }
  };
  res.sendFile("/attachment.html", options, err => {
    if (err) {
      next(err);
    } else {
      console.log("Sent:", "attachment.html");
    }
  });
});

// form-data表单提交
app.post("/user", (req, res, next) => {
  const form = new multiparty.Form();
  var name;
  var image;
  form.on("error", next);
  form.on("close", function(err) {
    console.log(err);
    console.log(name);
    console.log(image);
    res.send("资料提交成功!");
  });

  form.on("field", function(key, val) {
    if (key !== "image") name = val;
  });

  form.on("part", function(part) {
    if (!part.filename) return;
    if (part.name !== "image") return part.resume();
    image = {};
    image.filename = part.filename;
    image.size = 0;
    part.on("data", function(buf) {
      image.size += buf.length;
    });
  });

  form.parse(req);
});

app.listen(port, () => console.log(`App listening on port ${port}!`));

Затем мы создаем простую страницу отправки формы, где пользователю необходимо ввести свое имя и фотографию. мы помещаем эту страницу вpublicВ каталоге код страницы следующий:

<!--public/index.html-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>content-disposition 示例</title>
    <style>
      form {
        padding: 20px;
        border: 1px gray solid;
        background: yellowgreen;
      }
      .form-item {
        padding: 10px 0;
      }
      #commit {
        display: block;
        width: 80px;
        height: 30px;
        text-align: center;
        line-height: 30px;
        border: 1px solid #666;
        cursor: pointer;
        background: #eee;
      }
    </style>
  </head>
  <body>
    <h1>请提交您的个人资料</h1>
    <form>
      <div class="form-item">
        <label for="name">姓名:</label>
        <input type="text" name="name" id="name" />
      </div>
      <div class="form-item">
        <label for="pic">照片:</label>
        <input type="file" name="image" id="image" />
      </div>
      <div class="form-item"><span id="commit">提交</span></div>
    </form>
  </body>
  <script>
    function upload() {
      var formData = new FormData();
      var name = document.querySelector("#name").value;
      var image = document.querySelector("#image").files[0];
      formData.append("name", name);
      formData.append("image", image);

      var xhr = new XMLHttpRequest();
      xhr.open("POST", "/user");
      xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
          console.log(xhr.responseText);
          alert(xhr.responseText);
        }
      };
      xhr.send(formData);
    }

    document.querySelector("#commit").addEventListener(
      "click",
      function() {
        upload();
      },
      false
    );
  </script>
</html>

Кроме того, создайте еще одну HTML-страницу, которая будет использоваться для загрузки при доступе к ней браузера. Конкретное содержание кода является необязательным:

<!--attachment.html-->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>保存文件</title>
  </head>
  <body>
    保存文件
  </body>
</html>

воплощать в жизньnode app.jsЗапустить сервис, когда мы посетимlocalhost:3000/attach, вы можете обнаружить, что браузер загружает напрямуюattachment.html, и сохраните его какddd.html.

Ниже приведен скриншот страницы загрузки:

Ниже приведен скриншот заголовка ответа:

доступlocalhost:3000, вводим информацию в форму на главной странице и отправляем ее, после чего мы видим следующее изображениеContent-Dispositionформа отображения:

Суммировать

С тех пор, как мы используемContent-DispositionПо умолчаниюinlineне отображается в заголовке ответа запроса, поэтому я предполагаю, что многие внешние партнеры могутContent-DispositionНе знаю достаточно. Его основная цель — сообщить браузеру, что делать с содержимым ответа. Конечно, случайность в начале статьи была случайностью. Получив более подробное представление об этом в этой статье, я считаю, что друзья, работающие с интерфейсом, могут умело использовать его для достижения различных целей.

насчет нас

Передовая команда Kuaigou Taxi занимается обменом передовыми технологиями и регулярно публикует высококачественные статьи. Добро пожаловать, обратите внимание и лайкните.
Статья будет опубликована в паблике одновременно, если вы хотите получать актуальную информацию как можно быстрее, просто отсканируйте ее!

公众号二维码