fix: encode filename in datalake url (#10963)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov
2026-07-09 09:03:34 +07:00
committed by GitHub
parent 703f6d4139
commit e884e795a4
5 changed files with 54 additions and 6 deletions
@@ -57,14 +57,24 @@ describe('DatalakeStorage', () => {
expect(url).toBe(`${baseUrl}/blob/${workspace}/${file}`)
})
it('should handle special characters in parameters', () => {
it('should encode special characters in parameters', () => {
const workspace = 'test workspace'
const file = 'file 123'
const filename = 'my document.pdf'
const url = storage.getFileUrl(workspace, file, filename)
expect(url).toBe(`${baseUrl}/blob/${workspace}/${file}/${filename}`)
expect(url).toBe(`${baseUrl}/blob/test%20workspace/file%20123/my%20document.pdf`)
})
it('should encode slash in filename as a single path segment', () => {
const workspace = 'test-workspace'
const file = 'file-123'
const filename = 'folder/document.pdf'
const url = storage.getFileUrl(workspace, file, filename)
expect(url).toBe(`${baseUrl}/blob/${workspace}/${file}/folder%2Fdocument.pdf`)
})
it('should handle base URL with trailing slash', () => {
@@ -55,14 +55,24 @@ describe('FrontStorage', () => {
expect(url).toBe(`${baseUrl}/${workspace}/${filename}?file=${file}&workspace=${workspace}`)
})
it('should handle special characters in workspace and file names', () => {
it('should encode special characters in workspace, file, and filename', () => {
const workspace = 'test workspace'
const file = 'file 123'
const filename = 'my document.pdf'
const url = storage.getFileUrl(workspace, file, filename)
expect(url).toBe(`${baseUrl}/${workspace}/${filename}?file=${file}&workspace=${workspace}`)
expect(url).toBe(`${baseUrl}/test%20workspace/my%20document.pdf?file=file%20123&workspace=test%20workspace`)
})
it('should encode slash in filename as a single path segment', () => {
const workspace = 'test-workspace'
const file = 'file-123'
const filename = 'folder/document.pdf'
const url = storage.getFileUrl(workspace, file, filename)
expect(url).toBe(`${baseUrl}/${workspace}/folder%2Fdocument.pdf?file=${file}&workspace=${workspace}`)
})
it('should handle base URL with trailing slash', () => {
@@ -16,6 +16,7 @@
import { concatLink } from '@hcengineering/core'
import { FileStorage, FileStorageUploadOptions } from '../types'
import { uploadMultipart, uploadXhr } from '../upload'
import { encodePathSegment } from './utils'
const getPathname = (url: string): string => {
const base = window?.location?.href !== undefined ? window.location.href : 'http://localhost'
@@ -27,7 +28,12 @@ export class DatalakeStorage implements FileStorage {
constructor (private readonly baseUrl: string) {}
getFileUrl (workspace: string, file: string, filename?: string): string {
const path = filename !== undefined ? `/blob/${workspace}/${file}/${filename}` : `/blob/${workspace}/${file}`
const encodedWorkspace = encodePathSegment(workspace)
const encodedFile = encodePathSegment(file)
const path =
filename !== undefined
? `/blob/${encodedWorkspace}/${encodedFile}/${encodePathSegment(filename)}`
: `/blob/${encodedWorkspace}/${encodedFile}`
return concatLink(this.baseUrl, path)
}
@@ -16,6 +16,7 @@
import { concatLink } from '@hcengineering/core'
import { FileStorage, FileStorageUploadOptions } from '../types'
import { uploadXhr } from '../upload'
import { encodePathSegment } from './utils'
const getPathname = (url: string): string => {
const base = window?.location?.href !== undefined ? window.location.href : 'http://localhost'
@@ -27,7 +28,10 @@ export class FrontStorage implements FileStorage {
constructor (private readonly baseUrl: string) {}
getFileUrl (workspace: string, file: string, filename?: string): string {
const path = `/${workspace}/${filename ?? file}?file=${file}&workspace=${workspace}`
const encodedWorkspace = encodePathSegment(workspace)
const encodedFile = encodePathSegment(file)
const encodedFilename = encodePathSegment(filename ?? file)
const path = `/${encodedWorkspace}/${encodedFilename}?file=${encodedFile}&workspace=${encodedWorkspace}`
return concatLink(this.baseUrl, path)
}
@@ -0,0 +1,18 @@
//
// Copyright © 2026 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
export function encodePathSegment (value: string): string {
return encodeURIComponent(value)
}