我也面临同样的问题。似乎文件在输入本身上以某种方式损坏。我设法通过向控制台添加一些手动脚本来测试它:
const elements = [...document.querySelectorAll('input[type=file]')]
function testFile(file) {
const reader = new FileReader()´
reader.readAsDataURL(file)
reader.onloadend = function (e) { if (e.target.result) console.log("Success parsing file", file) }
reader.onerror = function (e) { console.log('Error parsing file', e) }
}
function register() {
elements.forEach(function(element) {
element.addEventListener('change', function (e) {
const file = e.target.files(0)
console.log('[onChange] Testing file:', file)
testFile(file)
})
})
}
function readFile(index) {
const file = elements[index].files[0]
console.log('[Manual] Testing file:', file)
testFile(file)
}
// Listen to file inputs changes
register()
// To check an input manually run
// readFile(index) - index refers to the index in the querySelectorAll array
我这样做是因为我无法在本地运行项目(公司非常限制 VPN)并且我必须在实时环境中进行测试(这很糟糕),但它可以验证文件完整性。
所以我可以注意到:
- 当我们将文件附加到输入时,文件看起来很好
- 经过一小段时间后,文件似乎以某种方式损坏,触发了
WebkitBlobResource error 1
- 这个问题是间歇性发生的,很难知道它什么时候会发生...很难调试
我还没有解决方案,我正在考虑这是 IOS 的 Webkit 问题(发生在 safari 和 chrome 上,chrome 基本上是 IOS 上的修改后的 safari,所以同样的 webkit 是有意义的)。但我试图在这里提供更多信息,以帮助找到解决方案。
使用可能的修复进行编辑(2020 年 10 月 15 日):
我做了一些研究,看来您的情况可能与 target="_blank/_self" 有关,请尝试两者,看看是否能解决您的问题。
我的问题与在 FormData 上发送文件有关。在我的情况下,我必须在更改时将文件转换为base64(因此我们不会丢失任何数据),然后在提交时再次将base64转换为文件并将原始文件的这个副本发送到FormData。代码下方:
/**
* For generating the base64 string, then I saved it in a variable to read it
* again when submitting. You can put this base64 as an anchor href as well to
* access it anywhere.
*/
export function createFileFromBase64({ data, name, type }) {
const BASE64_MARKER = ';base64,'
const parts = data.split(BASE64_MARKER)
const raw = window.atob(parts[1])
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
set(uInt8Array, i, raw.charCodeAt(i))
}
return new File([uInt8Array], name, { type })
}
export function processFile(file) {
return isIOS() ? createBase64FromFile(file) : file
}
/**
* For creating a file to be sent in the FormData from the giving base64 string.
*/
export function createFileFromBase64({ data, name, type }) {
const BASE64_MARKER = ';base64,'
const parts = data.split(BASE64_MARKER)
const raw = window.atob(parts[1])
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
set(uInt8Array, i, raw.charCodeAt(i))
}
return new File([uInt8Array], name, { type })
}
export const parseFile = file => {
return isIOS() ? createFileFromBase64(file) : file
}
这就是我设法解决 safari 问题的方法。
我希望它可以帮助别人!