如何将图像发布为xhr / ajax请求? (在iOS 10.0.2+中失败)

时间:2016-11-26 03:51:29

标签: javascript ios xmlhttprequest

使用XHR请求上传图像(来自dataUrl格式)似乎在iOS(10.0.2+)上失败,其他浏览器正在运行:最新的Chrome(54.0.2840.71),Firefox(50.0)。

请求似乎在JS中正确构造,但请求中没有附加实际数据。

var dataUrl = "data:image/jpeg;base64,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";

// create base64 encoded version of image
let parts = dataUrl.split(',');
let mime = parts[0].match(/:(.*?);/)[1];
let bstr = atob(parts[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
  while (n--) {
  u8arr[n] = bstr.charCodeAt(n);
}
let blob = new window.Blob([u8arr], {type: mime});
file = new window.File([blob], file.name);

// create formdata for uploading
let data = new FormData();
data.append('file', file, file.name);


// send the post request
var xhr = new XMLHttpRequest;
xhr.onload = function (oEvent) {
  // Uploaded.
  if ( oEvent.target.status == '200') {
    console.log('upload with XHR success');
  } else {
    console.log('upload with XHR error');
  }
};
xhr.open("POST", '/upload-endpoint', false);
xhr.send(data);

2 个答案:

答案 0 :(得分:0)

如何将图像上传到RESTful api的主要思路是使用multipart/form-data

如果您使用Swift 3.0,可以使用URLSession

尝试以下代码
import Cocoa

fileprivate extension ImageUploader {
    static let urlString = "/upload-endpoint"
    static let boundary = "---------------------------14737809831460499985746342449"
    static let contentType = "multipart/form-data; boundary=\(boundary)"
}

typealias CompletionBlock = (_ data: Data?, _ response: URLResponse?, _ error: Error?) -> Swift.Void

class ImageUploader {

    func recognize(with paths: [String], completionBlock: @escaping CompletionBlock) {

        guard paths.count > 0 else { return }

        let path = paths.first!

        guard let image = NSImage(contentsOfFile: paths.first!) else { return }

        let imgRep: NSBitmapImageRep = image.representations.first as! NSBitmapImageRep
        let data = imgRep.representation(using: .JPEG, properties: [:])

        var request = URLRequest(url: URL(string: ImageUploader.urlString)!)
        request.httpMethod = "POST"
        request.timeoutInterval = 10

        request.addValue(ImageUploader.contentType, forHTTPHeaderField: "Content-Type")
        var postbody = Data()
        postbody.append("\r\n--\(ImageUploader.boundary)\r\n".data(using: .utf8)!)
        postbody.append("Content-Disposition: form-data; name=\"file\"; filename=\"file\"\r\n".data(using: .utf8)!)
        postbody.append("Content-Type: application/octet-stream\r\n\r\n".data(using: .utf8)!)
        postbody.append(data!)
        postbody.append("\r\n--\(ImageUploader.boundary)\r\n".data(using: .utf8)!)

        request.httpBody = postbody

        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            completionBlock(data, response, error)
        }
        task.resume()

    }

}

答案 1 :(得分:0)

也许尝试使用fetch而不是xhr?

let dataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
let {name} = file

// First convert base64 to blob
fetch(dataUrl)
.then(res => res.blob())
.then(blob => {

    // Now upload the blob
    let fd = new FormData()
    fd.append('file', blob, name)

    fetch('/upload-endpoint', {method: 'POST', body: fd})
    .then(res => {
        console.log('upload with fetch success:', res.ok)
    })

})