POST двоичные данные из браузера на сервер JFrog/Artifactory без использования данных формы

Итак, мы получаем файл (файл изображения) в интерфейсе следующим образом:

//HTML

  <input type="file" ng-change="onFileChange">

//Javascript

  $scope.onFileChange = function (e) {
      e.preventDefault();
      let file = e.target.files[0];
      // I presume this is just a binary file
      // I want to HTTP Post this file to a server
      // without using form-data
   };

То, что я хочу знать, - это способ отправить этот файл на сервер без включения файла в качестве данных формы? Проблема в том, что сервер, на который я отправляю запрос HTTP POST, не знает, как хранить данные формы, когда он получает запрос.

Я считаю, что это правильный способ сделать это, но я не уверен.

  fetch('www.example.net', { // Your POST endpoint
    method: 'POST',
    headers: {
      "Content-Type": "image/jpeg"
    },
    body: e.target.files[0] // the file
  })
   .then(
    response => response.json() // if the response is a JSON object
  )

Ответы

Ответ 1

Вы можете напрямую прикрепить файл к телу запроса. Artifactory не поддерживает загрузку форм (и , похоже, они этого не планируют)

Вам все равно нужно будет как-то прокси-запрос, чтобы избежать проблем с CORS, и если вы используете учетные данные пользователя, вы должны быть осторожны в том, как вы к ним относитесь. Кроме того, вы можете использовать такую библиотеку, как http-proxy-middleware, чтобы избежать необходимости писать/тестировать/поддерживать логику прокси.

<input id="file-upload" type="file" />

<script>
function upload(data) {
  var file = document.getElementById('file-upload').files[0];
  var xhr = new XMLHttpRequest();
  xhr.open('PUT', 'https://example.com/artifactory-proxy-avoiding-cors');
  xhr.send(file);
}
</script>

Ответ 2

Наш интерфейс не мог HTTP POST напрямую на сервер JFrog/Artifactory. Таким образом, мы закончили использование сервера Node.js в качестве прокси-сервера, что не очень идеально.

Фронтальный:

// in an AngularJS controller:

     $scope.onAcqImageFileChange = function (e) {

          e.preventDefault();
          let file = e.target.files[0];
          $scope.acqImageFile = file;
      };

// in an AngularJS service

     createNewAcqImage: function(options) {

        let file = options.file;

        return $http({
          method: 'POST',
          url: '/proxy/image',
          data: file,
          headers: {
            'Content-Type': 'image/jpeg'
          }
        })
      },

Back-конец:

const express = require('express');
const router = express.Router();

router.post('/image', function (req, res, next) {

  const filename = uuid.v4();

  const proxy = http.request({
    method: 'PUT',
    hostname: 'engci-maven.nabisco.com',
    path: `/artifactory/cdt-repo/folder/${filename}`,
    headers: {
      'Authorization': 'Basic ' + Buffer.from('cdt-deployer:foobar').toString('base64'),
    }
  }, function(resp){
    resp.pipe(res).once('error', next);
  });

  req.pipe(proxy).once('error', next);
});

module.exports = router;

не то, что нам пришлось использовать запрос PUT для отправки изображения в Artifactory, а не POST, что-то связанное с Artifactory (сервер engci-maven.nabisco.com - это сервер Artifactory). Насколько я помню, у меня возникли проблемы с CORS при попытке отправить сообщение прямо из нашего интерфейса на другой сервер, поэтому нам пришлось использовать наш сервер в качестве прокси-сервера, чего я бы предпочел избежать, но пока все хорошо.