javascript - fetch - Saknas gräns i multipart/form-data POST
Jag vill skicka en new FormData() som body i en POST-förfrågan med fetch API
Operationen ser ut ungefär så här:
var formData = new FormData()
formData.append('myfile', file, 'someFileName.csv')
fetch('https://api.myapp.com',
{
method: 'POST',
headers: {
"Content-Type": "multipart/form-data"
},
body: formData
}
)
Problemet här är att gränsen, något som
boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu
kommer aldrig in i Content-Type:-huvudet
Det ska se ut så här:
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu
När du försöker samma operation med en new XMLHttpRequest(), på detta sätt:
var request = new XMLHttpRequest()
request.open("POST", "https://api.mything.com")
request.withCredentials = true
request.send(formData)
rubrikerna är korrekt inställda
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu
Så mina frågor är:
- hur får jag
fetchatt bete sig exakt somXMLHttpRequesti denna situation? - om detta inte är möjligt, varför?
Tack allihopa! Denna community är mer eller mindre anledningen till att jag har professionell framgång.
Svar #1
Lösningen på problemet är att uttryckligen sätta Content-Type till undefined så att din webbläsare eller vilken klient du än använder kan sätta det och lägga till det där gränsvärdet åt dig. Besvikande men sant.
Svar #2
Jag hade samma problem och kunde lösa det genom att exkludera Content-Type egenskapen, vilket tillät webbläsaren att automatiskt upptäcka och ställa in gränsen och innehållstypen.
Din kod blir:
var formData = new FormData()
formData.append('myfile', file, 'someFileName.csv')
fetch('https://api.myapp.com',
{
method: 'POST',
body: formData
}
)
Svar #3
Jag tog bort "Content-Type" och lade till 'Accept' i HTTP-huvuden och det fungerade för mig. Här är de huvuden jag använde,
'headers': new HttpHeaders({
// 'Content-Type': undefined,
'Accept': '*/*',
'Authorization':
"Bearer "+(JSON.parse(sessionStorage.getItem('token')).token),
'Access-Control-Allow-Origin': this.apiURL,
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE',
'Access-Control-Allow-Headers': 'origin,X-Requested-With,content-type,accept',
'Access-Control-Allow-Credentials': 'true'
})
Svar #4
Enligt FormData-dokumentationen bör du inte manuellt ställa in Content-Type-huvudet så att webbläsaren själv ställer in det korrekt:
Varning: När du använder FormData för att skicka POST-förfrågningar med XMLHttpRequest eller Fetch_API med Content-Type multipart/form-data (t.ex. när du laddar upp filer och Blobs till servern), ska du inte uttryckligen ange Content-Type-headern i förfrågan. Att göra det kommer att förhindra att webbläsaren kan sätta Content-Type-headern med gränsuttrycket som den kommer att använda för att avgränsa formulärfält i förfrågningskroppen.
Så om din kod (eller bibliotek/mellansoftware/etc) manuellt har satt Content-Type, har du två sätt att åtgärda det:
- skriv om din kod (eller vad du än använder) så att
Content-Typeinte sätts som standard - sätt
Content-Typetillundefinedeller ta bort det frånheadersför att låta din webbläsare göra sitt jobb
Svar #5
fetch(url,options)
- Om du sätter en sträng som
options.bodymåste du sättaContent-Typei begärans header, annars blir dettext/plainsom standard. Om options.body är ett specifikt objekt som
let a=new FormData()ellerlet b=new URLSearchParams(), behöver du inte ställa inContent-Typemanuellt. Det kommer att läggas till automatiskt.- för
a,det kommer att vara något liknande
- för
- för
bär detapplication/x-www-form-urlencoded;
multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gWSom du ser, läggs gränsen till automatiskt.
