diff --git a/addons/web/static/src/core/utils/urls.js b/addons/web/static/src/core/utils/urls.js index a46f215a062..0f2f32036fd 100644 --- a/addons/web/static/src/core/utils/urls.js +++ b/addons/web/static/src/core/utils/urls.js @@ -69,7 +69,14 @@ export function getDataURLFromFile(file) { } return new Promise((resolve, reject) => { const reader = new FileReader(); - reader.addEventListener("load", () => resolve(reader.result)); + reader.addEventListener("load", () => { + // Handle Chrome bug that creates invalid data URLs for empty files + if (reader.result === "data:") { + resolve(`data:${file.type};base64,`); + } else { + resolve(reader.result); + } + }); reader.addEventListener("abort", reject); reader.addEventListener("error", reject); reader.readAsDataURL(file); diff --git a/addons/web/static/src/legacy/js/core/utils.js b/addons/web/static/src/legacy/js/core/utils.js index 0759eb8d07e..de821729dc6 100644 --- a/addons/web/static/src/legacy/js/core/utils.js +++ b/addons/web/static/src/legacy/js/core/utils.js @@ -409,7 +409,12 @@ const utils = { return new Promise(function (resolve, reject) { var reader = new FileReader(); reader.addEventListener('load', function () { - resolve(reader.result); + // Handle Chrome bug that creates invalid data URLs for empty files + if (reader.result === "data:") { + resolve(`data:${file.type};base64,`); + } else { + resolve(reader.result); + } }); reader.addEventListener('abort', reject); reader.addEventListener('error', reject); diff --git a/addons/web/static/tests/core/utils/urls_tests.js b/addons/web/static/tests/core/utils/urls_tests.js index aa0fa379538..993a46fdfc8 100644 --- a/addons/web/static/tests/core/utils/urls_tests.js +++ b/addons/web/static/tests/core/utils/urls_tests.js @@ -1,7 +1,7 @@ /** @odoo-module */ import { browser } from "@web/core/browser/browser"; -import { getOrigin, url } from "@web/core/utils/urls"; +import { getDataURLFromFile, getOrigin, url } from "@web/core/utils/urls"; import { patchWithCleanup } from "../../helpers/utils"; QUnit.module("URLS", (hooks) => { @@ -59,4 +59,10 @@ QUnit.module("URLS", (hooks) => { }); assert.strictEqual(testUrl, "https://cors_server/cors_route/?my_param=1%2C2"); }); + + QUnit.test("getDataURLFromFile handles empty file", async (assert) => { + const emptyFile = new File([""], "empty.txt", { type: "text/plain" }); + const dataUrl = await getDataURLFromFile(emptyFile); + assert.strictEqual(dataUrl, "data:text/plain;base64,", "dataURL for empty file is not proper"); + }); }); diff --git a/addons/web/static/tests/legacy/core/util_tests.js b/addons/web/static/tests/legacy/core/util_tests.js index 3b5f6a0fad9..3288d0e0a53 100644 --- a/addons/web/static/tests/legacy/core/util_tests.js +++ b/addons/web/static/tests/legacy/core/util_tests.js @@ -1,6 +1,7 @@ /** @odoo-module **/ import utils from "web.utils"; +import { getDataURLFromFile } from "@web/core/utils/urls"; QUnit.module('core', {}, function () { @@ -301,4 +302,12 @@ QUnit.module('core', {}, function () { assert.deepEqual(sortBy(ints, null, 'desc'), [5, 2, 1]); assert.deepEqual(sortBy(objstrss, prop, 'desc'), [{ x: 'z' }, { x: 'b' }, { x: 'a' }]); }); + + QUnit.test('getDataURLFromFile handles empty file', async function (assert) { + assert.expect(1); + + const emptyFile = new File([""], "empty.txt", { type: "text/plain" }); + const dataUrl = await getDataURLFromFile(emptyFile); + assert.strictEqual(dataUrl, "data:text/plain;base64,", "dataURL for empty file is not proper"); + }); });