| Summary: | Fetch using FormData with file doesn't go through Service Worker | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | WebKit | Reporter: | nyro <cedric> | ||||||||||||||
| Component: | Service Workers | Assignee: | youenn fablet <youennf> | ||||||||||||||
| Status: | RESOLVED FIXED | ||||||||||||||||
| Severity: | Normal | CC: | ap, beidson, bugmail, cdumez, thiago.soares, webkit-bug-importer, youennf | ||||||||||||||
| Priority: | P2 | Keywords: | InRadar | ||||||||||||||
| Version: | Safari Technology Preview | ||||||||||||||||
| Hardware: | All | ||||||||||||||||
| OS: | Unspecified | ||||||||||||||||
| Attachments: |
|
||||||||||||||||
|
Description
nyro
2018-07-09 02:15:03 PDT
Thanks for the report. This is a known limitation of the service worker implementation at the moment in FetchBody::fromFormData. A potential workaround is to use blobs if possible although there might be limitations there as well. Youenn, following your recommandation, I ended up with the following:
#####################
formData.delete('file');
// get it as blob adn readd it as regular post field
// NB: File has to be recreated on server side using _files[file][name] and _files[file][data] to work as it was a regular file upload
var file = form.querySelector('input[type="file"]').files[0];
formData.append('_files[file][name]', file.name);
var reader = new FileReader();
reader.onload = function (e) {
formData.append('_files[file][data]', e.target.result);
doFetch(id, form, formData);
};
reader.readAsDataURL(file);
#####################
Which works, the request goes through the service Worker.
On server side, it becomes a little tricky regarding the language choosen, but I mentionned all the necessearry regarding PHP, the one I'm using.
I didn't implemented it yet on my production PWA, but I'll do it soon and come back here if I found out more gotcha.
In the mean time, I hope this will be fixed soon on Safari in order to remove all this code ;)
All the updated code and exemple have been updated on my demo page:
https://bugs.nyro.com/safariFileUpload/
Hello, Is there any news about that? It's been 2 years now... Hello, Is there any news about that? It's been 3 years now... Created attachment 448239 [details]
Patch
Created attachment 448241 [details]
Patch
Created attachment 448249 [details]
Patch
Created attachment 448282 [details]
Patch
Comment on attachment 448282 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=448282&action=review r=me with nits. > Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:278 > + if (!value.size()) { could probably use `value.empty()` > Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:284 > + builder.append(value.data(), value.size()); A bit disappointing that FragmentedSharedBuffer doesn't have an append() overload that takes a Span<>. We should probably add one. > Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:306 > + if (!value.size()) { could be `value.empty()` > Source/WebCore/Modules/fetch/FormDataConsumer.cpp:59 > + WTF::switchOn(m_formData->elements()[m_currentElementIndex++].data, [this](const Vector<uint8_t>& content) { May not need WTF:: > Source/WebCore/Modules/fetch/FormDataConsumer.cpp:70 > + consume(Span<const uint8_t> { content.data(), content.size() }); Can't you simply call `content.span()` ? > Source/WebCore/Modules/fetch/FormDataConsumer.cpp:121 > + m_callback(Span<const uint8_t> { content.data(), content.size() }); Source and destination are both a Span<const uint8_t>, why aren't we passing content directly instead of reconstructing a span? Am I missing something? *** Bug 183695 has been marked as a duplicate of this bug. *** Created attachment 448367 [details]
Patch for landing
Committed r287612 (245739@main): <https://commits.webkit.org/245739@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 448367 [details]. > > Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:278 > > + if (!value.size()) { > > could probably use `value.empty()` OK > > Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:284 > > + builder.append(value.data(), value.size()); > > A bit disappointing that FragmentedSharedBuffer doesn't have an append() > overload that takes a Span<>. We should probably add one. Added it. > > Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:306 > > + if (!value.size()) { > > could be `value.empty()` OK > > Source/WebCore/Modules/fetch/FormDataConsumer.cpp:59 > > + WTF::switchOn(m_formData->elements()[m_currentElementIndex++].data, [this](const Vector<uint8_t>& content) { > > May not need WTF:: Removed. > > Source/WebCore/Modules/fetch/FormDataConsumer.cpp:70 > > + consume(Span<const uint8_t> { content.data(), content.size() }); > > Can't you simply call `content.span()` ? Didn't know about this one, used it. > > Source/WebCore/Modules/fetch/FormDataConsumer.cpp:121 > > + m_callback(Span<const uint8_t> { content.data(), content.size() }); > > Source and destination are both a Span<const uint8_t>, why aren't we passing > content directly instead of reconstructing a span? Am I missing something? I was missing a WTFMove. |