Сегодня я потратил несколько часов, пытаясь заставить почтовый запрос работать с несколькими параметрами и файлом, который мне нужно загрузить.
Мне удалось заставить его работать с чистым javascript и XMLHttpRequest, но он не работает с Axios. Что я делаю неправильно?
Вот код, который работает с XMLHttpRequest:
let data = new FormData();
data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob([payload], { type: 'text/csv' }));
// this works
let request = new XMLHttpRequest();
request.open('POST', url);
request.send(data);
Какой будет версия «Axios»?
Вот одна из моих попыток (простая):
// this won't work
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
axios.post(url, data, config)
.then(response => console.log(response))
.catch(errors => console.log(errors));
Спасибо! И спасибо за отличную работу с Axios!
Код выглядит хорошо для меня. (Вам не нужно устанавливать Content-Type, но это и не важно.) Что происходит, когда вы пытаетесь отправить запрос через axios?
Я заметил, что установка Content-Type или нет ничего не меняет в этом случае. Когда я пытаюсь отправить запрос с помощью Axios, кажется, что данные идут как пустая строка, поэтому серверная часть отвечает ошибкой, связанной с отсутствующими параметрами.
Я использовал 0.9.1, но проблема сохраняется на 0.11.0.
Пожалуйста, дайте мне знать, если есть что-то еще, что я могу сделать, чтобы отладить это, хорошо?
Спасибо @nickuraltsev !
Не могли бы вы взглянуть, как выглядят ваши запросы на панели Chrome Dev Tools Network, и, если возможно, предоставить скриншот?
@nickuraltsev посмотрите, поможет ли это:
Я думаю, что заголовки запроса неверны.
Значит, нет запроса полезной нагрузки?
Ну, мы должны были бы, но данные идут как пустая строка. Я не знаю, что может его сломать (учитывая код, которым я поделился в своем первом посте).
Я понимаю. И для ваших запросов в Dev Tools нет раздела Request Payload, верно?
Возможно, проблема связана с заголовком. Когда тип контента установлен в объекте конфигурации в запросе, он объединяется, например
аксиос.пост(
'https://example.com/логин',
{emailAddress: электронная почта, пароль: hashedPassword},
{заголовки: {'тип контента': 'приложение/json'}}
);
тип содержимого заголовка входит как application/json,application/json
body не будет парситься в этом случае
@nickuraltsev верно! То, что вы видите на этом снимке экрана, — это все, что у меня есть в инструментах разработки.
@rrapant может быть прав, но я почти уверен, что установка 'Content-Type'
или нет, по крайней мере, в этом случае ничего не меняла. Я должен был бы проверить еще раз, чтобы быть уверенным.
@rrapant Проблема с повторяющимися значениями типа контента была исправлена в #317. Исправление будет включено в следующий релиз. Спасибо!
@rafaelbiten Я только что пытался воспроизвести проблему, но безрезультатно. Я использовал следующий код:
const data = new FormData();
data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob(['test payload'], { type: 'text/csv' }));
axios.post('http://httpbin.org/post', data);
Данные успешно отправлены на сервер:
@rafaelbiten Не могли бы вы попробовать отправить запрос с FromData на http://httpbin.org/post , как в моем фрагменте кода?
Закрытие на данный момент. Пожалуйста, не стесняйтесь открывать снова, если это необходимо.
Привет @nickuraltsev , у меня такая же проблема.
var fd = new FormData();
fd.append('file', this.refs.multipartfiles.files[0]);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
axios.post('/dataAPI/sendFile', {
"UploadCommand": fd
}, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Пожалуйста, найдите снимок экрана с информацией в моем заголовке ниже,
У меня есть вопрос: _поддерживает ли axios отправку файлов данных, состоящих из нескольких частей, на сервер узла?_
@Sreekhar Я не знаю, сработает ли это, но не могли бы вы добавить FormData в качестве второго аргумента вместо того, чтобы заключать его в другой объект?
axios.post('/dataAPI/sendFile', fd, config)
Если вам нужно использовать «UploadCommand» в качестве имени части, где находится файл, вам нужно использовать это
fd.append('UploadCommand', this.refs.multipartfiles.files[0]);
@yungpanda Я нашел для этого альтернативу. Думаю, теперь мне придется воссоздать API. В любом случае, я попытаюсь проверить, работает ли это, я буду держать тему в курсе. Спасибо за ответ.
@Sreekhar Установите для Content-Type значение undefined, чтобы позволить браузеру изменить его на multipart/form-data и автоматически добавить границу
@nickuraltsev это минимальный пример, который не работает на узле:
const data = new FormData();
data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
axios.post('http://httpbin.org/post', data).then(req => {
console.log('Req done: ', req)
}).catch(err => {
console.error('Error: ', err)
})
Ошибка: писать после конца
@krzkaczor Нашли ли вы какой-нибудь обходной путь для отправки multipart/form-data с помощью axios?
@PierreCavalet нет, вместо этого я использовал request-promise
.
@krzkaczor спасибо, тоже вынужден переключиться
@krzkaczor Попробуйте добавить тип содержимого, если вы еще этого не сделали.
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
let fd = new FormData();
fd.append('file',files[0])
return axios.post("http://localhost:5000/upload", fd, config)
@krzkaczor Я также сталкиваюсь с той же проблемой с axios и multipart/form-data. Можете ли вы опубликовать суть кода, который вы использовали с запросом-обещанием.
@dan-boa, иди сюда: https://gist.github.com/krzkaczor/bdbe09d4096b051a3c18387c4ca79a06 Он также показывает хак, как отправить строку в виде файла (установив путь)
Если кому интересно, вот пример использования FormData
с axios
. В основном вам нужно передавать данные в буфер и передавать правильные заголовки.
const concat = require("concat-stream")
const fd = new FormData()
fd.append("hello", "world")
fd.append("file", fs.createReadStream(file))
fd.pipe(concat(data => {
axios.post("/hello", data, {
headers: fd.getHeaders()
})
}))
У меня была такая же проблема (в браузере, а не в узле). Оказалось, что это работает, если вы вообще не устанавливаете заголовок Content-Type
и позволяете axios разобраться во всем (также проверьте, не установили ли вы этот заголовок по умолчанию в перехватчиках axios. Если вам нужны некоторые значения по умолчанию для остальных вызовов API, вы можете создать отдельный экземпляр axios для запросов FormData())
В итоге я использовал запрос-обещание на стороне узла при попытке загрузить на другой удаленный сервер.
Я переключился на запрос-обещание по той же причине. Любите аксиос иначе!
@guncha Ваш пример работал у меня в 0.15.3, пока я не попытался загрузить двоичный файл, который оказался закодирован как UTF8. Сообщение concat об использовании буфера устранило проблему.
const concat = require("concat-stream")
const fd = new FormData()
fd.append("hello", "world")
fd.append("file", fs.createReadStream(binaryFile))
fd.pipe(concat({encoding: 'buffer'}, data => {
axios.post("/hello", data, {
headers: fd.getHeaders()
})
}))
В качестве альтернативы я бы использовал обещание:
const promise = new Promise((resolve) => {
const fd = new FormData();
fd.append("hello", "world");
fd.append("file", fs.createReadStream(binaryFile));
fd.pipe(concat({ encoding: 'buffer' }, data => resolve({ data, headers: fd.getHeaders() })));
});
promise.then(({ data, headers }) => axios.post('/hello', data, { headers }));
const callApi = (url, params) => {
const formData = new FormData()
for(let name in params) {
let param = params[name]
if (typeof param === 'object') {
param = JSON.stringify(params[name])
}
formData.append(name, param)
}
return axios.post(url, formData)
.then(response => {
console.log(response)
})
}
@guncha работает на меня. Спасибо
такая же проблема здесь
просто добавьте границу к Content-Type
:
const request = require('axios');
const FormData = require('form-data');
const fs = require('fs');
let data = new FormData();
data.append('file1', fs.createReadStream('./image1.jpeg'), 'image1.jpeg');
data.append('file2', fs.createReadStream('./image2.jpeg'), 'image2.jpeg');
let options = {
method: 'POST',
url: 'http://localhost:3200/upload',
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
},
data
};
return request(options)
.then(response => {
console.log(response);
});
Привет,
Я получаю этот файл в формате json. Может ли кто-нибудь помочь мне, как мне преобразовать его в составной файл.
Используемая платформа — java8.
"body": "------WebKitFormBoundaryQsJGeBuR8e9dQ4Pm\r\nContent-Disposition: form-data; name=\"file\"; filename=\"backup prolog.txt\"\r\nContent-Type: text/plain\r\n\r\n%All the Pre-Defined relations\r\nconnected(hira,rohit,father).\r\nconnected(rohit,rakesh,father).\r\nconnected(ram,hira,father).\r\nconnected(kavri,hira,mother).\r\nconnected(hira,kavri,son).\r\nconnected(arun,vinayak,father).\r\nconnected(vinayak,arun,son).\r\nconnected(arun,shashi,husband).\r\nconnected(shashi,arun,wife).\r\nconnected(vinayak,vardaan,brother).\r\nconnected(vardaan,vinayak,brother).\r\nconnected(shashi,vinayak,mother).\r\nconnected(vinayak,shashi,son).\r\n\r\n\r\n\r\nconnected2(X,Y,D) :- connected(X,Y,D).\r\n%connected2(X,Y,D) :- connected(Y,X,D).\r\n\r\nnext_node(Current, Next,R, Path) :-connected2(Current, Next, R),not(member(Next, Path)).\r\n\r\nfunc(how,is,X,related,to,Y):-depth_first(X,Y,[X],P),write(P).\r\n%Procedure to Start the depth_first\r\ndepth_first(Goal, Goal, _, [Goal]).\r\n\r\ndepth_first(Start, Goal, Visited, [Start,is,R,of|Path]) :-next_node(Start, Next_node,R, Visited),depth_first(Next_node, Goal,[Next_node,R|Visited], Path).\r\n\r\n\r\n\r\n\r\n\r\n\r\n------WebKitFormBoundaryQsJGeBuR8e9dQ4Pm--\r\n"
Благодарность
Код работает в браузере, но не на узле.
const fdata = new FormData();
fdata.append('user', u);
fdata.append('hostnames', n.join(' '));
const host = localStorage.getItem('host');
const port = localStorage.getItem('port');
axios({
url: `http://${host}:${port}/hosts/remove`,
method: 'post',
data: fdata
}).then(response => {
if (response.status === 200) {
console.log(response.data);
console.log('Removed host successfully');
}
return null;
}).catch(er => console.log(er));
Привет @Sreekhar
Для меня я изменил конфигурацию на
const config = { headers: { 'Content-Type': 'application/json' } };
и это работало нормально
Пожалуйста, откройте снова, пока не будет какого-то последовательного ответа/рабочего процесса для этого. Похоже, что многие люди все еще испытывают проблемы с этим.
+1 повторно открыть
Сообщения HTTP, содержащие данные двоичного файла, отлично работают в axios v0.16.2.
// The following was tested successfully with axios v0.16.2
// Create a new form. Note: could also specify an existing form as
// the parameter to the FormData() constructor to copy all the elements
// from the existing form to the new one being created.
var tempFormData = new FormData();
var someNoteValue = 'Hello World';
var someAudioData = []; // populate this with data from file, with MediaRecorder() etc.
// Add form fields
tempFormData.set('SomeNote', 'Hello World');
tempFormData.set('SomeRecording', someAudioData[0], 'SampleRecording.webm');
// Optional: output list of form fields to the console for debugging
for (var pair of tempFormData.entries()) {
console.log('Form field: ' + pair[0] + ', ' + pair[1]);
}
// Call Axios to post the form to myurl
axios({
method: 'post',
url: 'myurl',
data: tempFormData,
config: { headers: {'Content-Type': 'multipart/form-data' }}
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
}
Также при использовании буферов для представления файла это сработало для меня:
const form = new FormData();
const fileBuffer = new Buffer(
'MM2 - noticeably shallower than the original - score: 101%', 'utf-8'
);
form.append('name', 'reviews.txt'); // additional form data field
form.append('file', fileBuffer, 'original-file-name.bar');
const res = await axios.post(`/uploadfile`, form, { headers: form.getHeaders() });
Важно отметить: любое из вышеперечисленных решений НЕ работает, если у вас есть какие-либо параметры данных по умолчанию, установленные в настройках по умолчанию экземпляра Axios. Вы также можете проверить, указали ли вы заголовок Content-Type по умолчанию в своем экземпляре Axios (через axios.defaults.headers и axios.defaults.parameters).
Это может быть не по делу, но проблема может быть связана с использованием body-parser
на стороне сервера. Я боролся с похожей проблемой и наткнулся на этот пост:
https://philna.sh/blog/2016/06/13/the-surprise-multipart-form-data/
TL; DR — body-parser
не обрабатывает multipart/form-data. Другими словами, проблема не в axios
, а в body-parser
. Возможно, поэтому буферные растворы, упомянутые выше, работают.
Я предполагаю, что эта функциональность предназначена для соображений безопасности, как указано здесь:
http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html
Я надеюсь, что это поможет кому-то!
У меня такая же проблема. Я использую Axios 0.16.2
и отправка по XMLHttpRequest
работает, но не по Axios.
У меня есть базовый объект FormData:
const formData = новые FormData();
formData.append('имя', 'textName');
Я попробовал предложение @Janekk :
axios({
method: 'post',
url,
withCredentials: true,
data: { formData },
})
тогда предложение @faalkhah :
const config = { headers: { 'Content-Type': 'application/json' } };
axios({
method: 'post',
url,
withCredentials: true,
data: { formData },
config,
})
или предложение @askona :
const config = { headers: { 'Content-Type': undefined } };
axios({
method: 'post',
url,
withCredentials: true,
data: { formData },
config,
})
Заголовок запроса application/json
, а formData
пуст.
Я не знаю, как попробовать исправить @demeter-macik, потому что кажется, что он работает только в серверной части https://stackoverflow.com/a/13454425/968379
всем привет,
У меня точно такая же проблема
мой код в клиенте
`
const url = '/file/uploadTest';
const formData = new FormData();
formData.append('file', file);
formData.append('params1', value);
formData.append('params2', value2)
const config = {
headers: {
'Content-Type': 'multipart/form-data',
}
}
axios.post(url,formData,config)`
на сервере парусов я записываю консоль req.body
Я обнаружил, что когда я вызываю запрос 10 раз, примерно 3-4 раза сервер не получает тело (тело пусто).
я проверил в devtool chrome, запрос все еще передает файл и тело в полезной нагрузке.
Я до сих пор не понял почему, но у меня есть решение
`код
const url = '/file/uploadTest';
const formData = new FormData();
formData.append('file', file);
formData.append('params1', value);
formData.append('params2', value2)
const config = {
headers: {
'Content-Type': 'multipart/form-data',
'params1': value,
'params2': value2
}
}
axios.post(url,formData,config)`
Привет @Sreekhar ,
Вы решили проблему? Я не нашел решения, может кто-нибудь помочь мне, пожалуйста.
Также заранее спасибо
Привет,
Я пытался опубликовать multiformdata (это API Eztext SMS)
используя аксиомы с node.js.
Он хорошо работает для следующего кода,
вернуть новое обещание (функция (разрешить, отклонить) {
var request = require("request");
var options = {
method: 'POST',
url: 'https://app.eztexting.com/sending/messages',
qs: {format: 'json'},
formData:
{
User: '**',
Password: '**',
'PhoneNumbers[0]': '8572222***',
Message: 'Appointment Reminder',
MessageTypeID: '1'
}
};
request(options, function (error, response, body) {
if (error) {
console.log(error);
reject(error);
}
else {
console.log(response);
resolve(response);
}
// console.log(body);
});
Но это не работает с axios, так как SMS не отправляется, но я получаю код состояния 200 для следующего запроса: -
вар аксиос = требуется ('аксиос');
axios.post('https://app.eztexting.com/sending/messages', {
qs: { format: 'json' },
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
formData:
{ User: '****',
Password: '2sH****5',
'PhoneNumbers[0]':'85722******',
Message: 'Hello Yahska',
MessageTypeID: 1 }
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
почему почтовый запрос выполняется с библиотекой «запрос», а не с Axios?
Вы пытались преобразовать данные из JSON в FormData без установки заголовка?
Заголовки для данных (т.е. помимо заголовков аутентификации) должны обрабатываться автоматически.
async function sendMessage(myJSONPayload){
try{
const data = convertJSON2FormData(myJSONPayload);
const response = await axios.post('https://app.eztexting.com/sending/messages', {
data
});
console.log(response);
} catch(ex){
console error(err);
}
}
sendMessage ({ User: '****',
Password: '2sH****5',
'PhoneNumbers[0]':'85722******',
Message: 'Hello Yahska',
MessageTypeID: 1 }
});
Для преобразования из JSON в FormData используйте что-то вроде этого ответа
Помните, что с вложенными ключами сложно обращаться. Например, при отправке данных в наш бэкенд это работает, если мы сгладим их следующим образом:
{a: {b: 2}} --> formData.append("a.b",2)
такая же проблема здесь.
конечно, @michaelscheurer! Установки заголовков запроса недостаточно: вы должны отправить FormData, чтобы заставить его работать. Это объект браузера, который будет сериализован со всеми необходимыми границами для работы с запросом... ни axios, ни vanilla js не преобразуют данные JSON в FormData для вас. Axios распознает, что это FormData, а также установит для вас заголовки, поэтому вам не нужно их устанавливать.
Попробуйте следовать моим предыдущим подсказкам ответа...
@Iamuertepeluda
Я пробовал следующее в соответствии с вашим предложением, но не повезло, такое же поведение, как я получаю статус 200 в порядке, но SMS не отправляется со следующим запросом
вар аксиос = требуется ('аксиос');
const FormData = require('form-data');
const form = new FormData();
//fo this jason I created a form
// formData:
// {
// User: '*****',
// Password
// :
// '******',
// 'PhoneNumbers[0]'
// :
// '8****2763',
// Message
// :
// 'Appointment Reminder',
// MessageTypeID
// :
// '1'
// }
form.append('User','****');
form.append('Password','*****');
form.append('PhoneNumbers[0]','*****');
form.append('Message','Appointment Reminder');
form.append('MessageTypeID','1');
axios.post('https://app.eztexting.com/sending/messages', form,
{
qs: {format: 'json'},
headers:
{
'content-type'
:
'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
}
}
)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
@ Ruchi2729 , вы используете node.js или браузер?
в браузере вам не нужно const FormData = require('form-data');
, так как FormData является родным.
Кроме того, попробуйте без установки заголовков и qs или попробуйте
axios.request({
url: "https://app.eztexting.com/sending/messages"
type: "post",
data: form //the instance of FormData of your stub
});
как я уже упоминал, он должен автоматически устанавливать заголовки в браузере
@ Ruchi2729 Ruchi2729 Я вижу, ты используешь узел, извини.
Я помню, как однажды использовал form-data
с axios, но не помню, работало ли это на самом деле.
Но вы уверены, что это правильный способ отправки SMS с помощью eztexting? Из их документов это кажется другим, например, вы должны использовать ключ API и собственный клиент узла...
Можем ли мы снова открыть это? Похоже, многие люди до сих пор сталкиваются с этим, в том числе и я. Например, этот запрос не доходит до сервера через axios, как ожидалось, но если я отправлю тот же файл через Postman как multipart/form-data
, все будет работать.
Редактировать: моя проблема заключалась в попытке отправить data-uri в кодировке base64 в виде данных формы. Если кто-то еще борется с той же проблемой, вот пример кода для его преобразования:
async function importCsv(data: CsvImportData): Promise<void> {
const formData = new FormData();
const headers = {'Content-Type': 'multipart/form-data'};
formData.append('csv', dataURItoFile(data.file, `upload_${Date.now()}.csv`));
try {
await axios.post('https://example.com/api/upload/csv', formData, {headers});
} catch(e) {
console.error(e);
}
}
function dataURItoFile(dataURI: string, defaultFileName: string): File {
let byteString: string;
const [metadata, data] = dataURI.split(',');
if (/base64$/.test(metadata)) {
byteString = atob(data);
} else {
byteString = unescape(data);
}
const mimetype: string = metadata.split(':')[1].split(';')[0];
const filename: string = (metadata.match(/name\=(.*);/) || [])[1] || defaultFileName;
let dataView: Uint8Array = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i++) {
dataView[i] = byteString.charCodeAt(i);
}
return new File([dataView], filename);
}
Эй, я имею в виду этот документ: - https://www.eztexting.com/developers/sms-api-documentation/rest#Sending
какой документ вы имеете в виду для ключа API и всего?
@Ручи2729
Извините, я перепутал с Nexmo, это другой SMS-сервис, у которого есть собственный клиент для узла 😅
Но в любом случае, согласно документации, на которую вы ссылались , вы можете избежать FormData, установив format
в json
и позволив axios отправлять полезную нагрузку JSON (вы можете позволить ей угадывать заголовки неявно по формату полезной нагрузки)
https://app.eztexting.com/sending/messages?format=json
Я боролся с этим намного дольше, чем хочу признать, так что, надеюсь, это кому-то поможет. Я использую axios, экспресс и экспресс-загрузку файлов. Я могу успешно загрузить в Node параметры, которые я добавил к FormData. Я подбираю файлы с помощью req.files, а остальные данные формы подбираю с помощью req.body['yourfilename']
Сервер (Экспресс):
router.post('/helper/amazon/upload', function(req, res) {
if (!req.files) {
return res.status(400).send('No files were uploaded.')
}
console.log(req.body.filename);
return console.log(req.files);
Интерфейс (аксиос)
const formData = new FormData();
formData.append('file', this.validFile);
formData.append('filename', 'trails/' + this.$route.params.id.split('-')[0] + '/camping/');
axios.post(
/api/helper/amazon/upload , formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
Результат:
У меня та же проблема, я вижу, что успешно отправляю данные файла с помощью своих инструментов разработки, но внутри моего контроллера мой $request->file('file') пуст
Мой компонент
представить форму() {
this.formData = новые данные формы();
this.formData.append('файл',this.$refs.file.files[0]);
this.formData.append('анализ',this.analyticsForm.analysis);
this.formData.append('_method','PATCH');
axios.post('/аналитика',
this.formData
,{заголовки: {'Content-Type': 'multipart/form-data'}}).then(response => this.isSubmittedRedirect(false,'/sources/'+this.source+'/description'+'') )
.catch((ошибка) => console.log(ошибка))
},
Я обнаружил, что делать что-либо с FormData было проблемой, поскольку MVC, похоже, не любит получать что-либо таким образом, потому что вы должны указать Content-Type как multipart/form-data
, и он выдавал исключение, когда я проверьте if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); }
, как указано на сайте Microsoft: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 2
Было лучше просто перевести мой файл в строку base64:
https://stackoverflow.com/questions/37134433/convert-input-file-to-byte-array/49676679#49676679
Этот пост может быть более подходящим для того, как это сделать, поскольку в этом примере я использовал DropZone:
https://stackoverflow.com/questions/32556664/getting-byte-array-through-input-type-file/49660172#49660172
И я расскажу об этом подробнее здесь :
Затем я мог бы создать объект JSON:
const myObj = {
file = myBase64String,
title = "myfileTitle.jpg"`
type = "image/jpeg"`
}
Вместо использования axios я просто использовал XMLHttpRequest.
const xhr = new XMLHttpRequest();
И откройте и установите заголовок:
xhr.open('POST', '/api/FileUpload/Post', true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8' );
xhr.withCredentials = true;
Я установил onreadystatechange
для захвата ответа:
xhr.onreadystatechange = (response) =>
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(response.target.responseText);
}
}
и отправить:
xhr.send(JSON.stringify(myObj));
Если вы используете axios, это, вероятно, будет:
try {
var axios = require('axios');
const config = {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
}
}
await axios.post('https://example.com/api/upload/post', myObj, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
catch(e) { console.log(e); }
На стороне MVC вам нужна соответствующая модель:
public class MyModel {
public string file { get; set; }
public string title { get; set; }
public string type { get; set; }
}
а затем укажите это в качестве параметра в вашем почтовом вызове с тегом [FromBody]:
[System.Web.Http.HttpPost]
public virtual JsonResult<string> Post([FromBody]MyModel myModelObject)
{
string strBase64FileString = myModelObject.file;
string strTitle = myModelObject.title;
string strFileType = myModelObject.type;
return Json(JsonConvert.SerializeObject(new { file = myModelObject.file, title = myModelObject.title, myModelObject.type }));
}
Вам должны вернуть то, что вы отправили. Обратите внимание: если вы реализуете это как тест, делайте это с очень маленьким файлом, чтобы вы не ждали вечно с возможностью блокировки браузера/памяти вашей системы.
@navyjax2
Я делал, как вы сказали, он работал с небольшим файлом, но мне нужно отправить большой файл (> 250Mo), и да, это блокировало мой браузер.
Да, для этого вы можете разбить массив файлов на куски управляемого размера и отправить блоки, имея метод на другом (серверном) конце, который может их повторно комбинировать, и дать ему параметр, чтобы он знает, какой это фрагмент (1-й, 2-й, 3-й и т. д.) и сколько всего фрагментов следует ожидать, прежде чем он обработает файл на стороне сервера. Но я думаю, что бы вы ни делали с файлом такого размера, вам придется подождать, пока он сделает свое дело. Придется быть осторожным с управлением памятью, если вы делаете это также по частям, потому что вам нужно будет каждый раз очищать или повторно использовать свои переменные, а не каждый раз повторно создавать новые версии одних и тех же переменных. ты делаешь блок. Один из немногих случаев, когда глобальная переменная хороша — или просто устанавливается в поле модели при каждом запуске.
Я согласен с @epferrari , рассмотрите возможность повторного открытия этого вопроса.
Можно отправить строку base64 с FormData в chrome, но это невозможно сделать с помощью axios в узле (v8.9.3).
И это работает с node-fetch...
const fetch = require('node-fetch')
const axios = require('axios')
const FormData = require('form-data')
const base64Img = require('base64-img')
const b64 = base64Img.base64Sync('./test.jpg').split('base64,')[1]
const form = new FormData()
form.append('b64_data', b64)
const headers = form.getHeaders()
// with node-fetch it worked
fetch('http://some.url', {
method: 'POST',
body: form,
headers,
}).then(res => res.text()).then(console.log).catch(console.log)
// not working with axios
axios({
method: 'POST',
url: 'http://some.url',
data: form,
headers,
}).then(console.log).catch(console.log)
=== обновление ===
Я не понимаю, я использую одни и те же заголовки для node-fetch и axios, и кажется, что они отправляют одни и те же данные формы на сервер, почему они заканчиваются по-разному?
Кстати, настоящий URL-адрес, который я публикую, взят отсюда , я делаю макет http-запроса браузера с помощью nodejs, чтобы отправить изображение на сервер и получить обратную ссылку.
Я обошел это, используя:
<input onChange="emitImageInfo(this)" type="file" multiple>
function emitImageInfo($event){
let files = $event.target.files
let formData = new FormData();
for (let i = 0; i < files.length; i++)
formData.append('image[' + i + ']', files[i])
axios.post('file/upload', formData)
.then((result) => { console.log('got it') })
.catch((err) => { console.log(err) })
}
это сработало:
axios.post (localhost: 3000/items, formData, { заголовки: { 'Content-Type': 'multipart/form-data' }});
У меня точно такая же проблема
не работает с голангом
Просто найдите простой способ во Vue, но я думаю, что его можно использовать и в других ситуациях.😀
Серверная часть: Express.js и пакет экспресс-загрузки файлов.
<template>
<div>
<input type="file"
name=""
id="file-upload"
multiple
@change="filesChange($event.target.files)">
<button @click="handleSubmit">Send</button>
</div>
</template>
<script>
export default {
data() {
return {
formData: new FormData(),
};
},
methods: {
filesChange(fileList) {
// First: append file to FormData
Array.from(Array(fileList.length).keys()).map(x => {
this.formData.append(fileList[x].name, fileList[x]);
});
},
handleSubmit() {
// Append Text
this.formData.append('username', 'Jeremy');
// Append Number: Will be string
this.formData.append('number', 9527);
// Append Array: Need to be converted to a string
this.formData.append('arrData', JSON.stringify([1, 2, 3]));
// Append Array: Need to be converted to a string
this.formData.append(
'objData',
JSON.stringify({ name: 'Jeremy', age: 28 })
);
this.axios({
method: 'post',
url: `file/multi-users`,
data: this.formData,
}).then(res => {
console.log(res);
});
},
},
};
</script>
Даже мы столкнулись с той же проблемой. Заголовок content -type был удален из java-скрипта реакции, после чего он работал нормально. Раньше граница не устанавливалась, когда вы явно устанавливали тип содержимого
РЕДАКТИРОВАТЬ: После дальнейшего чтения об этом кажется, что Express был проблемой с моей стороны. Надеюсь, это может быть полезно для других
Та же проблема здесь. @nickuraltsev НАСТОЯТЕЛЬНО рекомендует открыть тему заново.
Я пытаюсь опубликовать файл на моем сервере узлов через axios, используя следующий код:
let ff = new FileReader();
ff.onload = (ev) => {
var result = ev.target.result;
console.log(`result: ${result} of type ${typeof(result)}`);
axios.post('/test', {
file: result
})
.then((response) => {
console.log(`Response: ${response}`)
})
.catch((err) => {
console.log(`Test error: ${err}`);
})
}
var sampleFile = //getting the file here
ff.readAsArrayBuffer(sampleFile);
Тело запроса полностью пусто на стороне сервера.
Попытался отправить файл напрямую, прочитать файл как ArrayBuffer и прочитать файл как текст (хотя полезная нагрузка слишком велика), и все 3 не сработали.
Два года спустя:
Та же проблема...
@demeter-macik спасибо, добавление границ сработало для меня :smile:
const form = new FormData();
form.append('email', '[email protected]');
form.append('phone_no', '63');
form.append('phone_code', '9179303100');
if (logo) {
form.append('logo', logo);
}
const response = await axios({
method: 'post',
url: `${apiUrl}users`,
data: form,
headers: {
'content-type': `multipart/form-data; boundary=${form._boundary}`,
},
});
Это определенно работает для меня — все браузеры, включая Safari iOS.
Мой код выглядит примерно так:
функция samplePost (конфигурация) {
// save reference this
let that = this;
// can optionally pull in form fields from an existing HTML form)
let myForm = document.getElementById('myForm');
let myFormData = new FormData(myForm);
// add in data from config.data if applicable
if (config && config.data) {
that.objToStr(config.data, '', myFormData);
for (let n2 in config.data) {
if (config.data.hasOwnProperty(n2)) {
myFormData.set(n2, config.data[n2]);
}
}
}
if (config.binaryFiles && config.binaryFiles.length > 0) {
for (let i = 0; i < config.binaryFiles.length; i = i + 1) {
let thisFile = config.binaryFiles[i];
myFormData.append(thisFile.fieldName, thisFile.binaryData, thisFile.fileName)
}
}
let axiosConfig = {
method: 'post',
url: config.url,
data: myFormData,
onUploadProgress: config.onUploadProgress,
};
if (config && config.binaryFiles && config.binaryFiles.length > 0) {
axiosConfig.headers = {'Content-Type': 'multipart/form-data'};
}
else {
axiosConfig.headers = {'Content-Type': 'application/x-www-form-urlencoded'};
}
const ax = axios.create();
// note that passing in config to the constructor is broken as of axios v0.19.0-beta.1
// So we work around by passing in config to the request() method
ax.request(axiosConfig)
.then(function (response) {
// handle success
alert(response.data);
})
};
// вызываем samplePost для загрузки
образецПост({
url: 'async',
data: {somefield: 'some value'}, //note: passes in as form fields
// optionally include array of binary files
binaryFiles: thisFileList
});
От: Антонио Васкес[email protected]
Отправлено: вторник, 11 сентября 2018 г., 11:23
Кому: axios/ axios [email protected]
Копия: DavidRueter [email protected] ; Комментарий [email protected]
Тема: Re: [axios/axios] Не удается заставить работать .post с Content-Type: multipart/form-data (#318)
4 часа и считая, чтобы сделать почтовый запрос из Safari. Все еще не происходит... какого черта, ребята??
Ни одно из решений здесь не сработало у меня... :(
—
Вы получаете это, потому что вы прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub https://github.com/axios/axios/issues/318#issuecomment-420371510 или отключите ветку https://github.com/notifications/unsubscribe-auth/AFbi6JQBv06LTwL4z3HIAlvXAXDyps1- ks5uZ_9wgaJpZM4Ibm_z . https://github.com/notifications/beacon/AFbi6BSPfwPvNaWPFSdvtLKRYXS1m4uKks5uZ_9wgaJpZM4Ibm_z.gif
это сработало и для меня, спасибо @arvi
twiliosms = асинхронный (Codigo) => {
var FormData = требуют('данные формы');
вар фс = требуется ('фс');
переменная форма = новые данные формы();
form.append('Кому', '+524772773737');
form.append('От', '+737373737');
form.append('Тело', Codigo);
пытаться {
пусть axapi = ожидание axios(
{
URL: '2010-04-01/Accounts/AC8aa53c907943af79234414bb725c2cd3/Messages.json',
базовый URL: «https://api.twilio.com»,
заголовки: {'тип содержимого': multipart/form-data; boundary=${form._boundary}
,},
данные: форма,
авторизация: {
имя пользователя: 'AC8aa53c907943af79234414bb725c2cd3',
пароль: * ,
},
метод: 'пост',
}
)
} поймать (e) {console.error(e)}
}
Я блуждаю по этой библиотеке, все еще требующей самостоятельных обходных путей для сообщений с данными формы....
Любое обновление?
У меня есть аналогичная ошибка в NodeJS 10.11.0 и Axios 0.18.0 (см. № 1892). Я пробовал исправить @arvi , но это не работает.
для меня это работает:
let formData = new FormData(document.querySelector('#form'));
axios.post("/api/xxx", formData).then(console.log).catch(console.error)
и это не сработает
let formData = new FormData(document.querySelector('#form'));
axios.post("/api/xxx", {data: formData}).then(console.log).catch(console.error)
помните, что формат параметра postdata должен быть (url , FormData)
, а не (url, {data: FormData})
beforeAll(function (done) {
//parse form fields
var parsefields = function(req,res){
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
if (err) res.status(404).json(err)
else res.status(200).json(fields);
});
}
router.route('parsefields').post(parsefields)
//start server
s = express()
s.use('/',router)
s.listen(4000,(err)=>{done(err)})
done()
});
it('should parse and return form fields', function (done) {
const fd = new FormData()
fd.append('key','value')
axios({
method: 'POST',
url: 'http://localhost:4000/parsefields',
data: fd,
headers : fd.getHeaders(),
}).then(function (res) {
expect(res).to.exist
expect(res.body.key).to.equals('value')
}).catch(err => {
expect(err).not.to.exist
})
done()
});
});
У меня такая же проблема. Получение 404 без ошибок. Использование formidable для парсера форм, экспресс и аксиом.
Я не знаю, поможет ли это кому-нибудь, но я видел эту проблему только в Safari и исправил ее с помощью formdata-polyfill . Safari должен изначально поддерживать FormData.append(), но, может быть, реализация немного отличается?
РЕДАКТИРОВАТЬ: я был неправ: я использовал URL-адрес, созданный из BLOB-объекта. Как только я начал использовать правильный блоб, все заработало как шарм!
У меня такая же проблема с Blob, пока я могу загрузить файл. Преобразование из BLOB-объекта в файл просто, но я хотел бы знать, является ли это ошибкой или я неправильно истолковал синтаксис:
`` js
upload () {
let data = new FormData()
data.append('file', this.croppedFile)
data.append('blob', this.croppedBlob, 'blob.jpeg')
axios.post('/api/fp/process/', data, {
headers: {
'Accept':
текст/обычный`,
},
})
croppedFile is derived from croppedBlob with this simple code:
` return new File([this.cropImg], this.file.name, { type: this.file.type })`
Firefox dev tools show:
------WebKitFormBoundarytmInU7WtcHvmgYbc
Content-Disposition: данные формы; имя = «клякса»
------WebKitFormBoundarytmInU7WtcHvmgYbc
Content-Disposition: данные формы; имя="файл"; имя файла="dscn2950.jpg"
Тип содержимого: изображение/jpeg
блоб:http :// локальный:8080/9a6446d1-1ca2-4fd3-a6c8-8b36d863c146
------WebKitFormBoundarytmInU7WtcHvmgYbc--
```
Согласно документации mozilla formData.append , кажется, я мог бы использовать объекты Blob.
Что меня застряло, так это то, что мой сервер неправильно обрабатывал файлы, исправил это с помощью https://www.npmjs.com/package/multer .
это полезно для меня! Спасибо!
У меня ничего здесь не работало, потому что мой код был совершенно хорош.
Настоящая проблема была с файлом, который я перетаскивал из результатов поиска Windows — Chrome не смог найти реальное местоположение и сломал весь анализ FormData. Перейдите к файлу и перетащите его, чтобы решить проблему.
Всем привет,
Пожалуйста помогите.
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1
Авторизация: носитель [YOUR_AUTH_TOKEN]
Content-Type: multipart/related; граница = foo_bar_baz
Длина контента: [NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]
--foo_bar_baz
Тип содержимого: приложение/json; кодировка = UTF-8
{
"имя": "мойОбъект"
}
--foo_bar_baz
Тип содержимого: изображение/jpeg
[JPEG_ДАННЫЕ]
--foo_bar_baz--
axios не поддерживает составной/связанный тип запроса
Для меня это был (наверное) глоток. Потому что я получал ошибку с мини-файлами на моем сервере. Я вручную удалил все из папки dist, оставил тип содержимого неопределенным, и все работает как положено.
Таким образом, у вас будет что-то вроде:
formdata.append("selectPaymentType", $scope.extraFields.selectPaymentType);
formdata.append("pickupMethod", $scope.extraFields.selectPickupType);
пусть запрос = {
метод: «ПОСТ»,
URL: baseURL + «заказы»,
данные: формдата,
заголовки: {
«Тип контента»: не определено,
'x-токен доступа': $scope.userToken
}
};
$ http (запрос)
.успех (функция (г) {})
.ошибка (функция () {});
PS: Это отрывок... Я также прилагаю файлы и много других полей...
СЕРВЕР:
var form = new multiparty.Form({uploadDir: './uploads/orders/'});
form.parse (требование, функция (ошибка, поля, файлы) {
//ВАШ КОД ЗДЕСЬ
})
Привет, пожалуйста, мне нужна помощь: я получил «файл: это значение не должно быть пустым». когда я пытаюсь опубликовать изображение с помощью fetch :
handleSubmit = (event) => {
event.preventDefault();
//const { category } = this.state;
console.log(this.state.file)
let formData = new FormData();
formData.append("file",this.state.file);
formData.append("name",this.state.name);
alert('You Added a new Category Named ' + this.state.file);
fetch(`${process.env.REACT_APP_BASE_URL}/category/image`, {
method: 'POST',
body: formData
}).then(res => res.json()).then(err => console.log(err));
}
конструктор (реквизит) {
супер (реквизит);
this.state = {
name: '',
file: null
,
isLoaded: false,
isEditMode: false,
}
}
```
Для всех это сработало для меня.
Если вы используете входной файл, вы должны использовать MULTER в своем router.post('/') как промежуточное программное обеспечение, прежде чем получать другие поля ввода.
проверьте свой axios.create, эти заголовки должны быть "заголовки: {}" и не использовать данные. Вот так:
экземпляр var = axios.create({
заголовки: {
// 'Тип содержимого': 'application/x-www-form-urlencoded;charset=UTF-8',
},
// данные: {},
параметры: {}
});
По сей день это не работает на nodejs. Подход request-promise
также сработал для меня.
Потратил 2 дня, пытаясь заставить это работать с axios в nodejs. Потратил 30 секунд, чтобы заставить его работать с запросом-обещанием в nodejs.
Я пробовал разные решения, но в конце концов решил эту проблему, добавив заголовки:
const FormData = require('form-data')
const axios = require('axios')
const form = new FormData()
form.append('foo', 'bar')
await axios.post('http://myserver', form, { headers: form.getHeaders() })
@ Гугрош Да. да. да.
Полдня потратил на выяснение, связано ли это с конфигурацией клиента или сервера.
В конце концов, headers: form.getHeaders()
сделал свое дело.
Перешел на got
, потому что он просто _работает_ с formData
и multipart/form-data
- https://github.com/sindresorhus/got 🙌
Близко, но нет сигарного Axios 👋
const form = new FormData()
const stream = fs.createReadStream(file.path)
form.append('file', stream, file.name)
try {
await got.post('http://example.com', { body: form })
} catch (error) {
next(error)
}
Вы можете сделать это следующим образом:
handleSubmit = (e: любой) => {
e.preventDefault();
константные данные = новые данные формы();
data.append('product_csv', this.state.csvfile);
пусть accessToken = localStorage.getItem('access_token');
аксиомы
.post('/загрузить', данные,
{ заголовки:
{ 'Content-Type': 'multipart/form-data', авторизация: accessToken }
})
.тог(рес => {
console.log('разрешение', разрешение);
});
};
@Googrosh Великолепно, .getHeaders()
у меня тоже сработало. Я не могу сказать вам, сколько часов я потратил на это. Спасибо!
Я использую React Native. И я закончил эту проблему, используя rn-fetch-blob
. Очень плохо :(
У меня такая же проблема, она просто не работает с простыми данными FormData без какого-либо файла, и .getHeaders() не помогает. Перемещено в «получил» библиотеку, которая просто работает. Упомянул это здесь также https://github.com/form-data/form-data/issues/458 (я использую Node v12)
2020 ES6 способ сделать
Имея форму в html, я привязывал данные так:
ДАННЫЕ:
form: {
name: 'Joan Cap de porc',
email: '[email protected]',
phone: 2323,
query: 'cap d\ou'
file: null,
legal: false
},
при отправке:
async submitForm() {
const formData = new FormData()
Object.keys(this.form).forEach((key) => {
formData.append(key, this.form[key])
})
try {
await this.$axios.post('/ajax/contact/contact-us', formData)
this.$emit('formSent')
} catch (err) {
this.errors.push('form_error')
}
}
См.: https://github.com/axios/axios/issues/789#issuecomment-508114703 .
На принимающей стороне, если вы используете Express, вам нужен multer . body-parser не обрабатывает запросы, состоящие из нескольких частей.
@DespertaWeb Не работает, когда нет файлов.
Самый полезный комментарий
@rafaelbiten Я только что пытался воспроизвести проблему, но безрезультатно. Я использовал следующий код:
Данные успешно отправлены на сервер: