richardgirges / express-fileupload

Simple express file upload middleware that wraps around busboy
MIT License
1.52k stars 261 forks source link

Example with XMLHttpRequest, FormData and blob on frontend #262

Closed jfoclpf closed 3 years ago

jfoclpf commented 3 years ago

Good day, all the examples your provide on front-end relate to HTML forms, though I'm using apache cordova and thus I'm trying to upload a file as blob using merely XMLHttpRequest and FormData constructors. I'm getting desperate since req.files is always falsy. I'm here around for 2 days and I can't figure out where's the problem

Frontend

var blob = new Blob([new Uint8Array(file)], { type: 'application/octet-stream' })
var fd = new FormData()
fd.append('blob', blob, 'img.jpg')

var xhr = new XMLHttpRequest()
xhr.open('POST', remoteUrl)
xhr.setRequestHeader('Content-Type', 'multipart/form-data')
xhr.onload = function () {
  if (xhr.status === 200) {
    console.log(`File ${fileUri} uploaded succesfully to url ${remoteUrl}`)
    if (typeof callback === 'function') { callback() }
  } else {
    console.error(`Error uploading file ${fileUri}. Server returned ${xhr.status}`)
    if (typeof callback === 'function') { callback(xhr.status) }
  }
}
xhr.onerror = function (err) {
  console.error(`Error uploading file ${fileUri} to server`)
  console.error(err)
  if (typeof callback === 'function') { callback(err) }
}
xhr.send(fd)

The backend was already working, thus there's no need to paste it here. Do you see any reasons why req.files is falsy?

Thanks a lot in advance

jfoclpf commented 3 years ago

With debug option set to true I just get this line: Express-file-upload: Request is not eligible for file upload!

jfoclpf commented 3 years ago

I'm debugging now your lib/isEligibleRequest.js and it fails on hasAcceptableContentType. I'm doing my homework :)

jfoclpf commented 3 years ago

Found it :) Man, a comma ; in content type was missing xhr.setRequestHeader('Content-Type', 'multipart/form-data;')

You should change line 1 of that file: https://github.com/richardgirges/express-fileupload/blob/master/lib/isEligibleRequest.js#L1

From const ACCEPTABLE_CONTENT_TYPE = /^(multipart\/.+);(.*)$/i; to const ACCEPTABLE_CONTENT_TYPE = /^(multipart\/.+);?(.*)$/i;

Note the ?, which means the comma is optional

jfoclpf commented 3 years ago

I found the issue, finally :) No need to define content type on XMLHttpRequest cause it gets automatically and indeed this line was important fd.append('file', blob, fileName)

Now it's working. You may add this example on your folder

Frontend

var blob = new Blob([new Uint8Array(this.result)], { type: 'application/octet-stream' })
var fd = new FormData()

fd.append('file', blob, fileName)

var xhr = new XMLHttpRequest()
xhr.open('POST', remoteUrl, true)
xhr.onload = function () {
  if (xhr.status === 200) {
    console.success(`File ${fileUri} uploaded succesfully to url ${remoteUrl}`)
    if (typeof callback === 'function') { callback() }
  } else {
    console.error(`Error uploading file ${fileUri}. Server returned ${xhr.status}`)
    if (typeof callback === 'function') { callback(xhr.status) }
  }
}
xhr.onerror = function (err) {
  console.error(`Error uploading file ${fileUri} to server`)
  console.error(err)
  if (typeof callback === 'function') { callback(err) }
}
xhr.send(fd)