在请求后发送文件

时间:2018-08-06 10:34:02

标签: javascript jquery ajax

在python中,我发送如下文件:

with open('D:\\someimage.jpg', 'rb') as image:
imager = image.read()
files = {'image': imager}
r = requests.post(url, files=files)

我想在js中做类似的事情,但是我总是收到400 Bad Request错误。我认为问题是我不知道文件应具有的类型。我尝试将其以初始“文件”类型,作为数组缓冲区,作为二进制字符串的形式传递-没有任何效果。这是我的代码:

var reader = new FileReader();
reader.readAsArrayBuffer(aFiles[0]);
reader.onload = function () {
var arrayBuffer = this.result,
array = new Uint8Array(arrayBuffer),
binaryString = String.fromCharCode.apply(null, array);
jQuery.ajax({
    url: '/streamer', 
    method: 'POST',
    files: {'image': binaryString},
    success: function(response) {
        alert(response);
    },
    error: function(xhr, status, error) {
       alert(JSON.parse(xhr.responseText));
    }});

1 个答案:

答案 0 :(得分:0)

如果您需要发送更多字段,则可以将文件作为FormData(多部分/表单数据)发送,或者如果您只想直接发送二进制文件,则可以作为Blob发送。

jQuery试图在处理您发送的数据时变得聪明。但是jQuery不了解FormData或Blob,它将其视为对象并且做错了事。这就是为什么您需要设置processData = false并不要通过执行contentType = false设置错误的请求内容类型,而只需让xhr自己执行。

var fd = new FormData();
fd.append('image', aFiles[0] /*, optional filename */)

var req = jQuery.ajax({
  url: '/streamer', 
  method: 'POST',
  data: fd, // sends fields with filename mimetype etc
  // data: aFiles[0], // optional just sends the binary
  processData: false, // don't let jquery process the data
  contentType: false // let xhr set the content type
});

// jQuery is promise A++ compatible and is the todays norms of doing things 
req.then(function(response) {
  console.log(response)
}, function(xhr) {
  console.error('failed to fetch xhr', xhr)
})

但是,如果您仅支持具有fetch api的最新浏览器,那么您就不需要jQuery了。

var req = fetch('/streamer', {
  method: 'post',
  body: fd /* or aFile[0]*/
}); // returns a promise

req.then(function(response) {
  // returns status + response headers
  // but not yet the body, 
  // for that call `response[text() || json() || arrayBuffer()]` <-- also promise

  if (res.ok) {
    // status code was 200-299
  } else {
    // status was something else
  }
}, function(xhr) {
  console.error('failed due to network error or cross domain')
})