-
Notifications
You must be signed in to change notification settings - Fork 1k
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
feat(http): support for FormData requests #6708
Conversation
It wasn't checking for lower case, resulting in json being passed back instead of a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks the same as #6206. Needs to be updated to merge.
Thanks for working on this! Would it be possible to see an example of how sending formdata in a post request would work? I've been trying all sorts of things and passing a FormData object with some appended data never makes it to the server. If I use a json object then it works fine. I tried setting the dataType to |
@kjr-lh , I tried to update to However, when I tried the code below, I'm getting this on xcode terminal
|
I thought that this PR would allow using CapacitorHttp to make requests with FormData. Is that not the case? I tested using const dataURItoBlob = (dataURI: string) => {
// Split the `dataURI` at the comma.
let splitDataURI = dataURI.split(',');
// Get the mime-type from the `dataURI`
let mimeType = splitDataURI[0].split(':')[1].split(';')[0];
// Get the base64 string
const base64 = splitDataURI[1];
// Decode the base64 string
let binary = atob(base64);
// Create an 8-bit unsigned array
let array = [];
for(let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
// Return the blob object with appropriate mime-type
return new Blob([new Uint8Array(array)], {type: mimeType});
}
const upload = async () => {
const photo = await Camera.getPhoto({
resultType: CameraResultType.DataUrl,
source: CameraSource.Photos,
correctOrientation: true,
quality: 90,
allowEditing: false
})
const blob = dataURItoBlob(photo.dataUrl)
const formData = new FormData()
formData.append('file', blob)
fetch(useAppConfig().getApiUrl('/upload-test'), {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
} |
In case this is helpful for anyone else, the above code using fetch does end up triggering a native However, I couldn't find a way to just issue the |
This comment was marked as off-topic.
This comment was marked as off-topic.
This doesn't add Blob support yet - if you can pass your data as |
Hi @mikeelemuel, your code looks like it should be okay.. the only thing I can think to try would be to include the filename , e.g.
But I'm really doubtful this will help 😞 I'm afraid I don't have enough Swift experience to diagnose that error |
@kjr-lh Thanks!
I may try that eventually. However, removing the file from formData and just leaving a plain input with text also didn't work for me as mentioned here #6708 (comment) The data doesn't arrive to the server. |
@kjr-lh Awesome, thanks. However, I don't see that you are using CapacitorHttp there. Per my previous comments, I have it working with |
Fetch is capacitorhttp now (from one of the 4.x versions) - Capacitor patches fetch and XMLHttpRequest with it's own versions that go through the native layer https://capacitorjs.com/docs/apis/http The code that is handling Files / FormData is in the fetch/XMLHttpRequest implementations, so you'll be skipping it if you go directly to CapacitorHttp request/post. You could encode the data yourself, but it'd be much simpler to use fetch |
I understand that from my tests, but what was confusing to me since I was waiting for the FormData update is that there's nothing in the documentation about having to use fetch directly to be able to also use FormData/Files. What made it even more confusing is that I went through the code changes to try to understand how to use FormData and saw this: So basically a new option was added to HttpOptions (which is used with CapacitorHttp) to specify file/formData export interface HttpOptions {
url: string;
method?: string;
params?: HttpParams;
data?: any;
headers?: HttpHeaders;
/**
* How long to wait to read additional data. Resets each time new
* data is received
*/
readTimeout?: number;
/**
* How long to wait for the initial connection.
*/
connectTimeout?: number;
/**
* Sets whether automatic HTTP redirects should be disabled
*/
disableRedirects?: boolean;
/**
* Extra arguments for fetch when running on the web
*/
webFetchExtra?: RequestInit;
/**
* This is used to parse the response appropriately before returning it to
* the requestee. If the response content-type is "json", this value is ignored.
*/
responseType?: HttpResponseType;
/**
* Use this option if you need to keep the URL unencoded in certain cases
* (already encoded, azure/firebase testing, etc.). The default is _true_.
*/
shouldEncodeUrlParams?: boolean;
/**
* This is used if we've had to convert the data from a JS type that needs
* special handling in the native layer
*/
dataType?: 'file' | 'formData';
} Finally, what's even more confusing is that when using fetch with FormData, everything does work, and it ends up using CapacitorHttp under the hood per my previous image Which makes me believe there must be a way to use CapacitorHttp directly to be able to use the Capacitor API rather than using fetch. I am happy to have it working now. I am just trying to provide feedback from the point of view of someone that uses the framework and was using the community/http-plugin before to upload files which had an uploadFile method. The documentation could use a bit more information on this, similar to the FileSystem docs for downloads where I also had to go through the test app code to figure out how to migrate. |
You can @jreviews, if you mean this: import { CapacitorHttp } from "@capacitor/core"
import { Filesystem } from "@capacitor/filesystem"
export async function fileUpload(file: {
name: string
path: string
mimeType: string
}) {
const formData = new FormData()
const contents = await Filesystem.readFile({ path: file.path })
const blob = new Blob([contents.data], { type: file.mimeType })
formData.append("file", blob, file.name)
const response = await CapacitorHttp.request({
url: "https://example.com/upload",
dataType: "file",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
})
// ...
} |
I really don't expect this to work as-is - I think you'd need to have converted the form data already to a base 64 encoded string (take a look at what As it is now, I think capacitor will just try to convert the data to json, which means it will be sent to the native layer as Now that the http plugin is part of capacitor core, I think the expectation is that everyone will just use fetch, as it's a more usual interface and code using it will also work on the web |
Thanks! I've released an update using |
We also need to send a Blob through post method. We currently have mobile app env. with Ionic 7, Capacitor 5, Angular 16. In our case we need FormData, which we send it through post method to client's API. Client's API accepts only Blob. We've tried angular/common/http which works great on dev env., but in production We get hit by client's CORS policy. So we need to use plugin which uses native libraries, like this one. We would really appreciate it if there would be a way to send Blob directly through post with FormData. Thanks! |
@Mimateam The code I shared before #6708 (comment) using fetch works to send FormData with blob and it also makes request using native libraries. Just make sure you enable fetch patching per the capacitor http docs https://capacitorjs.com/docs/apis/http#configuration |
We have now another problem. When using this approach #6708 (comment) then we cannot access images on mobile phone from cache when picking images from camera or gallery. Solution to allow Blob directly through post with FormData would be highly appreciated and would solve all problems. We don't see why this should not be implemented? |
No update on this ? |
This is #6206 for capacitor 5 (tested against 5.0.5)
Also includes a fix for the
content-type
bug mentioned here