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 при попытке отправить сообщение прямо из нашего интерфейса на другой сервер, поэтому нам пришлось использовать наш сервер в качестве прокси-сервера, чего я бы предпочел избежать, но пока все хорошо.