-
-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] [iOS] formData with blob is not sending http request #295
Comments
Hi indraraj, |
Hi silkimen, When you add blob to request it is not making any request we are temporary logging all the request and saving in temp column, But with blob it is not making any request to backend. I already have catch block i just don't get any error. Okay btw let me remove the header part Edit: Tested with blob and changed content-type to multipart it is not making any request, enabled the debug level at Apache. Also I had catch block so there i had no error. |
Okay, I see. I've tried to reproduce your problem on my device (iPhone XR running iOS 13.2) and also on a simulator (iPad 5th generation running iOS 12.4). I'm using the e2e specs suite which you can find here: test/e2e-specs.js lines 802-847 being the relevant ones. |
I see you have this in code |
Okay, that‘s interesting. Did you try to run exactly the code from my e2e specs? I‘d like to know what‘s going wrong here. |
I am facing similar issue, I followed the same procedure which is in test/e2e-specs.js. I am trying to upload images to aws s3, using blob. Xcode debugger crashes throwing error |
@sarathi0333 Can you please attach a Xcode screenshot? I'd like to know where exactly this problem occurs. |
@sarathi0333 Unfortunately I can't reproduce your problem. Please attach an extract of your JS code. And please try to run EXACTLY the code you can find in the e2e specs file (running against httpbin.org). I'd like to find out if it's related to something received from the server. Which device are you using? Which iOS version? |
Same problem. API works from Postman but not in angular. The plugin seems not working when a try to make a put request in multipart and formData. It never return any response or error... |
Hi guys, Some context - I am overriding the uploadData method of dropzone to work using cordova-plugin-advanced-http on my capacitor app. Regardless of whether I am sending a blob or file object, the append method receives only the type string, e.g. "[Object blob]", so is checking if "[Object blob]" instanceof "Global.Blob", which clearly it isn't. This returns it as an unknown type and so is rejected as an incorrect data type for dataSerializer multipart. A sample of my code: dz_uploadData = function(files, dataBlocks) {
var _this16 = this;
var url = this.resolveOption(this.options.url, files);
var formData = new window.top.cordova.plugin.http.ponyfills.FormData();
var dto = {
uuid: files[0].upload.uuid,
name: files[0].name,
chunkIndex: dataBlocks[0].chunkIndex,
totalChunkCount: files[0].upload.totalChunkCount
};
for (var key in dto) {
var value = dto[key];
formData.append(key, value);
}
for (var i = 0; i < dataBlocks.length; i++) {
var dataBlock = dataBlocks[i];
formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
}
window.top.cordova.plugin.http.setDataSerializer("multipart");
window.top.cordova.plugin.http.setRequestTimeout(extendedTimeout);
let requestOptions = {
data: formData,
headers: {
"Content-Type": "multipart/form-data;"
}
};
window.plenty_admin.REST.postOne(
url,
requestOptions,
function(response) {
window.top.cordova.plugin.http.setDataSerializer("json");
window.top.cordova.plugin.http.setRequestTimeout(standardTimeout);
console.log(response);
_this16._finishedUploading(files, xhr, e);
},
function(error) {
window.top.cordova.plugin.http.setDataSerializer("json");
window.top.cordova.plugin.http.setRequestTimeout(standardTimeout);
console.error(error);
_this16._handleUploadError(files, xhr);
}
);
}; I hope this can help to identify the problem? --EDIT-- The reason for this comes from the FormData.append ponyfill for sure: FormData.prototype.append = function(name, value, filename) {
if (global.File && value instanceof global.File) {
// nothing to do
} else if (global.Blob && value instanceof global.Blob) { // it is an instance of Blob, not Global.Blob...
// mimic File instance by adding missing properties
value.lastModifiedDate = new Date();
value.name = filename || '';
} else {
value = String(value);
}
this.__items.push([ name, value ]);
}; The patch I have working for this file is: FormData.prototype.append = function(name, value, filename) {
if (global.File && value instanceof global.File) {
// nothing to do
} else if (global.Blob && value instanceof global.Blob || value.constructor.name === "Blob") {
// mimic File instance by adding missing properties
value.lastModifiedDate = new Date();
value.name = filename || '';
} else {
value = String(value);
}
this.__items.push([ name, value ]);
}; plugins/cordova-plugin-advanced-http/www/helpers.js also needs patching to replace: if (entry.value[1] instanceof global.Blob || entry.value[1] instanceof global.File) {
var reader = new global.FileReader();
reader.onload = function() {
result.buffers.push(base64.fromArrayBuffer(reader.result));
result.names.push(entry.value[0]);
result.fileNames.push(entry.value[1].name || 'blob');
result.types.push(entry.value[1].type || '');
processFormDataIterator(iterator, textEncoder, result, onFinished);
};
return reader.readAsArrayBuffer(entry.value[1]);
} with if (
entry.value[1] instanceof global.Blob ||
entry.value[1].constructor.name === "Blob" ||
entry.value[1] instanceof global.File ||
entry.value[1].constructor.name === "File"
) {
var reader = new global.FileReader();
reader.onload = function() {
result.buffers.push(base64.fromArrayBuffer(reader.result));
result.names.push(entry.value[0]);
result.fileNames.push(entry.value[1].name || 'blob');
result.types.push(entry.value[1].type || '');
processFormDataIterator(iterator, textEncoder, result, onFinished);
};
return reader.readAsArrayBuffer(entry.value[1]);
} If anyone can explain why instanceof no longer works to identify the object I would appreciate an explanation! |
I'm running into the same issue. Here is some more information:
fileContent is just a plain UTF-8 string. Expected
None send File with formData.append('file', new File([fileContent], fileName));
My fileContent string does not contain "[object Object]" lol formData.append('file', new File([fileContent], fileName), fileName);
I get that formData.append('file', new File([fileContent], fileName, {type: 'application/octet-stream'}));
formData.append('file', new File([fileContent], fileName, {type: 'text/html'}));
How I'm POSTing let formData = new FormData();
formData.append('file', ...);
this.mobileHttp.setDataSerializer('multipart');
return this.mobileHttp.post(url, formData, {}) The same exact System info
|
I wasn't able to get it working tonight but I got a bit further by stepping through things. One of the issues was that I was using declare var cordova;
...
new cordova.plugin.http.ponyfills.FormData() The issue I am running into now is that when I am debugging, the /**
* Constructor.
* name {DOMString} name of the file, without path information
* fullPath {DOMString} the full path of the file, including the name
* type {DOMString} mime type
* lastModifiedDate {Date} last modified date
* size {Number} size of the file in bytes
*/
var File = function (name, localURL, type, lastModifiedDate, size) {
this.name = name || '';
this.localURL = localURL || null;
this.type = type || null;
this.lastModified = lastModifiedDate || null;
// For backwards compatibility, store the timestamp in lastModifiedDate as well
this.lastModifiedDate = lastModifiedDate || null;
this.size = size || 0;
// These store the absolute start and end for slicing the file.
this.start = 0;
this.end = this.size;
}; So I tried passing the file as a formData.append('file', new Blob([fileContent]), fileName); or formData.append('file', new Blob([fileContent], { type: 'text/html' }), fileName); or const textEncoder = new TextEncoder();
formData.append('file', new Blob([textEncoder.encode(fileContent).buffer]), fileName); but While debugging I noticed that |
Same problem for me on Android. I'm currently unable to send a POST request with a Blob or File in the formData. No request is sent to the server (I also checked Apache logs) and the Promise remains pending without throwing any error. I searched for days how to make it works but I finally surrendered, it seems it is impossible to send a file with this Plugin. Anyone else facing the same issue ? Does someone has a workaround ? |
I am also facing the same issue for the iOS with sending the multipart request with Blob object |
@RomanRobot I've checked your app, but that's not what I meant as MVP. 😅
Please check MDN reference of FormData/append. It says:
So, I think your Blob instance is not recognized as a Blob. That could be the reason why it's serialized as string representation and not read correctly by FileReader in helpers.js#L443. The question is why? Do you have set up some polyfills or alternative implementations of Blob or FileReader? |
@silkimen I believe this is due to an ongoing issue with ionic/capacitor apps and Angular's Zone library. I implemented this suggested solution in your library, and it fixed my issue. Please let me know if you would like me to submit a PR. Thanks Edit: The fix actually needs to listen to onloadend as well, instead of onload. Otherwise the file result doesn't get saved. |
@bsbechtel How would someone apply this fix themselves? I tried updating the code in
but while it compiles, I seem to get this in my output window after submitting any HTTP requests:
If I revert those changes to It's my first time trying to change a library like this. New to Angular. Something to note, while I am excited to potentially have a working solution to this issue I'm worried about some reports of performance issues reported below that solution you linked: |
Also, to answer your question @silkimen
I don't think so. The only one I see is the default one in the
and a bunch of comments. |
@RomanRobot I ended up overwriting the prototype method in a bit of a hacky way until the library can be updated. I put this in main.ts:
|
@bsbechtel Freakin' awesome! That got me unblocked on that finally. Thank you! |
@bsbechtel thanks for the hacky way after I had spent days on it and saw this eventually. It deserves a PR. |
I'm having the same issue with Ionic + Capacitor + Angular on an Android device. Sending FormData works well but the second I add a Blob to the FormData, the http request never gets send and i have no error. |
I have the exact same issue on Android (Ionic 7, Capacitor 5, Angular 16). In my case I need FormData, which I send it through post method to client's API. Client's API accepts only Blob. When I add Blob to my FormData, nothing happens in the request. Just like in your case. I've tried angular/common/http which works great on my dev env., but in production I get hit by client's CORS policy. So I need to use plugin which uses native libraries, like this one. We really need this to be added asap. Thanks! |
Describe the bug
It is not sending any request when i am sending blob but it is working fine when i am just sending text
like this form.append("name", "indraraj")
System info
Are you using ionic-native-wrapper?
Capacitor CLI : 1.3.0
@capacitor/core : 1.4.0
Minimum viable code to reproduce
If applicable, add formatted sample coding to help explain your problem.
e.g.:
console before sending actual request
Screenshots
If applicable, add screenshots to help explain your problem.
ionic info
The text was updated successfully, but these errors were encountered: