Skip to content

Commit 2814759

Browse files
fix: use new binary upload format to prevent multipart corruption (#854)
Following opendatateam/udata#3597 then the replacement by opendatateam/udata#3598 (waiting werkzeug fix), we don't need to change the code but adding a test. --------- Co-authored-by: Nicolas KEMPF <[email protected]>
1 parent e8aa3d2 commit 2814759

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { test, expect } from '@playwright/test'
2+
import * as fs from 'fs'
3+
import * as path from 'path'
4+
import * as os from 'os'
5+
import { clickOutside } from '../helpers'
6+
7+
const __dirname = import.meta.dirname
8+
9+
/**
10+
* Generate a file where a \r byte falls exactly at the chunk boundary.
11+
*/
12+
function generateFileWithCRLFAtChunkBoundary(filePath: string, chunkSize: number): void {
13+
const buffer = Buffer.alloc(chunkSize + 1000, 'a')
14+
buffer[chunkSize - 1] = 0x0D // \r at end of first chunk
15+
fs.writeFileSync(filePath, buffer)
16+
}
17+
18+
test('can upload a large file with CRLF at chunk boundary (chunked upload)', async ({ page }) => {
19+
const chunkSize = 2 * 1000 * 1000 // 2MB
20+
const tempDir = os.tmpdir()
21+
const testFilePath = path.join(tempDir, 'test-chunked-upload.csv')
22+
const uniqueTitle = `Test chunked upload CRLF ${Date.now()}`
23+
24+
generateFileWithCRLFAtChunkBoundary(testFilePath, chunkSize)
25+
26+
await page.goto('/')
27+
await page.getByRole('button', { name: 'Publier sur data.gouv.fr' }).click()
28+
await page.getByRole('link', { name: 'Un jeu de données' }).click()
29+
await page.getByRole('button', { name: 'Commencer la publication' }).click()
30+
await page.getByTestId('producer-select').click()
31+
await page.getByRole('option', { name: 'Admin User' }).click()
32+
await page.getByRole('textbox', { name: 'Titre *' }).fill(uniqueTitle)
33+
await page.getByTestId('markdown-editor').fill('Test dataset for chunked upload with CRLF line endings.')
34+
await page.getByTestId('markdown-editor').press('Tab')
35+
await page.getByText('Il est recommandé d\'avoir une').click()
36+
await page.getByTestId('select-frequency').click()
37+
await page.getByRole('option', { name: 'Inconnu' }).click()
38+
await clickOutside(page)
39+
await page.getByRole('button', { name: 'Suivant' }).click()
40+
41+
// Upload the large file
42+
await page.getByRole('button', { name: 'Ajoutez des fichiers' }).click()
43+
const fileChooserPromise = page.waitForEvent('filechooser')
44+
await page.getByRole('button', { name: 'Parcourir' }).click()
45+
const fileChooser = await fileChooserPromise
46+
await fileChooser.setFiles(testFilePath)
47+
48+
await page.getByRole('button', { name: 'Envoyer' }).click()
49+
await page.getByRole('button', { name: 'Suivant' }).click()
50+
51+
// Wait for upload to complete
52+
await page.waitForLoadState('networkidle')
53+
await page.waitForTimeout(500)
54+
55+
// Verify no chunk size mismatch error
56+
await expect(page.getByText('Chunk size mismatch')).not.toBeVisible()
57+
58+
// Go to the dataset page and verify the file is present
59+
await page.getByRole('link', { name: uniqueTitle }).click()
60+
await expect(page.getByText('test-chunked-upload.csv')).toBeVisible()
61+
})

0 commit comments

Comments
 (0)