mirror of https://github.com/Squidex/squidex.git
40 changed files with 378 additions and 359 deletions
@ -0,0 +1,31 @@ |
|||
// ==========================================================================
|
|||
// FileExtensions.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.IO; |
|||
|
|||
// ReSharper disable InvertIf
|
|||
|
|||
namespace Squidex.Infrastructure |
|||
{ |
|||
public static class FileExtensions |
|||
{ |
|||
public static string FileType(this string fileName) |
|||
{ |
|||
try |
|||
{ |
|||
var fileInfo = new FileInfo(fileName); |
|||
|
|||
return fileInfo.Extension.Substring(1).ToLowerInvariant(); |
|||
} |
|||
catch |
|||
{ |
|||
return "blob"; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { FileSizePipe, KNumberPipe } from './..'; |
|||
|
|||
describe('FileSizePipe', () => { |
|||
it('should calculate correct human file size', () => { |
|||
const pipe = new FileSizePipe(); |
|||
|
|||
expect(pipe.transform(50)).toBe('50 B'); |
|||
expect(pipe.transform(1024)).toBe('1.0 kB'); |
|||
expect(pipe.transform(1260000)).toBe('1.2 MB'); |
|||
}); |
|||
}); |
|||
|
|||
describe('KNumberPipe', () => { |
|||
it('should calculate correct human string', () => { |
|||
const pipe = new KNumberPipe(); |
|||
|
|||
expect(pipe.transform(0)).toBe('0'); |
|||
expect(pipe.transform(-1)).toBe(''); |
|||
expect(pipe.transform(50)).toBe('50'); |
|||
expect(pipe.transform(1024)).toBe('1k'); |
|||
expect(pipe.transform(1260000)).toBe('1000k'); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,50 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { Pipe, PipeTransform } from '@angular/core'; |
|||
|
|||
@Pipe({ |
|||
name: 'sqxKNumber', |
|||
pure: true |
|||
}) |
|||
export class KNumberPipe implements PipeTransform { |
|||
public transform(value: number) { |
|||
if (value > 1000) { |
|||
value = value / 1000; |
|||
|
|||
if (value < 10) { |
|||
value = Math.round(value * 10) / 10; |
|||
} else { |
|||
value = Math.round(value); |
|||
} |
|||
|
|||
return value + 'k'; |
|||
} else if (value < 0) { |
|||
return ''; |
|||
} else { |
|||
return value.toString(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Pipe({ |
|||
name: 'sqxFileSize', |
|||
pure: true |
|||
}) |
|||
export class FileSizePipe implements PipeTransform { |
|||
public transform(value: number) { |
|||
let u = 0, s = 1024; |
|||
|
|||
while (value >= s || -value >= s) { |
|||
value /= s; |
|||
u++; |
|||
} |
|||
|
|||
return (u ? value.toFixed(1) + ' ' : value) + ' kMGTPEZY'[u] + 'B'; |
|||
} |
|||
} |
|||
|
|||
@ -1,75 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { ApiUrlConfig, DateTime, Version } from 'framework'; |
|||
|
|||
import { FileHelper } from './file-helper'; |
|||
import { AssetDto } from './../services/assets.service'; |
|||
|
|||
describe('FileHelper', () => { |
|||
const now = DateTime.now(); |
|||
const user = 'user'; |
|||
|
|||
it('should calculate correct human file size', () => { |
|||
expect(FileHelper.fileSize(50)).toBe('50 B'); |
|||
expect(FileHelper.fileSize(1024)).toBe('1.0 kB'); |
|||
expect(FileHelper.fileSize(1260000)).toBe('1.2 MB'); |
|||
}); |
|||
|
|||
it('should calculate icon', () => { |
|||
expect(FileHelper.fileIcon('video/mp4')).toBe('/images/asset_video.png'); |
|||
expect(FileHelper.fileIcon('application/text')).toBe('/images/asset_generic.png'); |
|||
expect(FileHelper.fileIcon('application/msword')).toBe('/images/asset_doc.png'); |
|||
}); |
|||
|
|||
it('should calculate file type', () => { |
|||
expect(FileHelper.fileType('video/mp4', 'test.mp4')).toBe('mp4'); |
|||
expect(FileHelper.fileType('video/mp4')).toBe('mp4'); |
|||
expect(FileHelper.fileType('application/text', 'test.txt')).toBe('txt'); |
|||
expect(FileHelper.fileType('application/text')).toBe('text'); |
|||
|
|||
expect(FileHelper.fileType('invalid')).toBeUndefined(); |
|||
expect(FileHelper.fileType(null!)).toBeUndefined(); |
|||
}); |
|||
|
|||
it('should calculate asset info for image asset', () => { |
|||
const asset = new AssetDto('1', user, user, now, now, 'File.png', 50, 1, 'image/png', true, 100, 20, new Version('123')); |
|||
|
|||
expect(FileHelper.assetInfo(asset)).toBe('100x20px, 50 B'); |
|||
}); |
|||
|
|||
it('should calculate asset info for text asset', () => { |
|||
const asset = new AssetDto('1', user, user, now, now, 'File.txt', 50, 1, 'text/plain', false, 0, 0, null!); |
|||
|
|||
expect(FileHelper.assetInfo(asset)).toBe('50 B'); |
|||
}); |
|||
|
|||
it('should return asset name', () => { |
|||
const asset = new AssetDto('1', user, user, now, now, 'File.txt', 50, 1, 'text/plain', false, 0, 0, null!); |
|||
|
|||
expect(FileHelper.assetName(asset)).toBe('File.txt'); |
|||
}); |
|||
|
|||
it('should return empty string for invalid asset', () => { |
|||
expect(FileHelper.assetInfo(undefined!)).toBe(''); |
|||
expect(FileHelper.assetInfo(null!)).toBe(''); |
|||
}); |
|||
|
|||
it('should return preview url', () => { |
|||
const apiUrl = new ApiUrlConfig('my/'); |
|||
const asset = new AssetDto('1', user, user, now, now, 'File.txt', 50, 1, 'text/plain', false, 0, 0, new Version('123')); |
|||
|
|||
expect(FileHelper.assetPreviewUrl(apiUrl, asset)).toBe('my/api/assets/1?version=123'); |
|||
}); |
|||
|
|||
it('should return download url', () => { |
|||
const apiUrl = new ApiUrlConfig('my/'); |
|||
const asset = new AssetDto('1', user, user, now, now, 'File.txt', 50, 1, 'text/plain', false, 0, 0, new Version('123')); |
|||
|
|||
expect(FileHelper.assetUrl(apiUrl, asset).startsWith('my/api/assets/1?q=')).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -1,112 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { ApiUrlConfig, MathHelper } from 'framework'; |
|||
import { AssetDto } from './../services/assets.service'; |
|||
|
|||
const mimeMapping = { |
|||
'pdf': 'pdf', |
|||
'vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx', |
|||
'vnd.openxmlformats-officedocument.wordprocessingml.template': 'docx', |
|||
'vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx', |
|||
'vnd.openxmlformats-officedocument.spreadsheetml.template': 'xlsx', |
|||
'vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx', |
|||
'vnd.openxmlformats-officedocument.presentationml.template': 'pptx', |
|||
'vnd.openxmlformats-officedocument.presentationml.slideshow': 'pptx', |
|||
'msword': 'doc', |
|||
'vnd.ms-word': 'doc', |
|||
'vnd.ms-word.document.macroEnabled.12': 'docx', |
|||
'vnd.ms-word.template.macroEnabled.12': 'docx', |
|||
'vnd.ms-excel': 'xls', |
|||
'vnd.ms-excel.sheet.macroEnabled.12': 'xlsx', |
|||
'vnd.ms-excel.template.macroEnabled.12': 'xlsx', |
|||
'vnd.ms-excel.addin.macroEnabled.12': 'xlsx', |
|||
'vnd.ms-excel.sheet.binary.macroEnabled.12': 'xlsx', |
|||
'vnd.ms-powerpoint': 'ppt', |
|||
'vnd.ms-powerpoint.addin.macroEnabled.12': 'pptx', |
|||
'vnd.ms-powerpoint.presentation.macroEnabled.12': 'pptx', |
|||
'vnd.ms-powerpoint.template.macroEnabled.12': 'pptx', |
|||
'vnd.ms-powerpoint.slideshow.macroEnabled.12': 'pptx' |
|||
}; |
|||
|
|||
export module FileHelper { |
|||
export function assetUrl(apiUrl: ApiUrlConfig, asset: AssetDto): string { |
|||
return apiUrl.buildUrl(`api/assets/${asset.id}?q=${MathHelper.guid()}`); |
|||
} |
|||
|
|||
export function assetName(asset: AssetDto): string { |
|||
return asset.fileName; |
|||
} |
|||
|
|||
export function assetPreviewUrl(apiUrl: ApiUrlConfig, asset: AssetDto) { |
|||
return apiUrl.buildUrl(`api/assets/${asset.id}?version=${asset.version.value}`); |
|||
} |
|||
|
|||
export function assetInfo(asset: AssetDto): string { |
|||
let result = ''; |
|||
|
|||
if (asset != null) { |
|||
if (asset.pixelWidth) { |
|||
result = `${asset.pixelWidth}x${asset.pixelHeight}px, `; |
|||
} |
|||
|
|||
result += FileHelper.fileSize(asset.fileSize); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
export function fileType(mimeType: string, fileName?: string) { |
|||
if (fileName) { |
|||
const parts = fileName.split('.'); |
|||
|
|||
if (parts.length > 1) { |
|||
return parts[parts.length - 1].toLowerCase(); |
|||
} |
|||
} |
|||
if (mimeType) { |
|||
const parts = mimeType.split('/'); |
|||
|
|||
if (parts.length === 2) { |
|||
const mimeSuffix = parts[1].toLowerCase(); |
|||
|
|||
return mimeMapping[mimeSuffix] || mimeSuffix; |
|||
} |
|||
} |
|||
return undefined; |
|||
} |
|||
|
|||
export function fileIcon(mimeType: string) { |
|||
const mimeParts = mimeType.split('/'); |
|||
|
|||
let mimeIcon = 'generic'; |
|||
|
|||
if (mimeParts.length === 2) { |
|||
const mimePrefix = mimeParts[0].toLowerCase(); |
|||
const mimeSuffix = mimeParts[1].toLowerCase(); |
|||
|
|||
if (mimePrefix === 'video') { |
|||
mimeIcon = 'video'; |
|||
} else { |
|||
mimeIcon = mimeMapping[mimeSuffix] || 'generic'; |
|||
} |
|||
} |
|||
|
|||
return `/images/asset_${mimeIcon}.png`; |
|||
} |
|||
|
|||
export function fileSize(bytes: number) { |
|||
let u = 0, s = 1024; |
|||
|
|||
while (bytes >= s || -bytes >= s) { |
|||
bytes /= s; |
|||
u++; |
|||
} |
|||
|
|||
return (u ? bytes.toFixed(1) + ' ' : bytes) + ' kMGTPEZY'[u] + 'B'; |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// ==========================================================================
|
|||
// FileExtensionsTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Xunit; |
|||
|
|||
namespace Squidex.Infrastructure |
|||
{ |
|||
public class FileExtensionsTests |
|||
{ |
|||
[Theory] |
|||
[InlineData("test.mp4", "mp4")] |
|||
[InlineData("test.MP4", "mp4")] |
|||
[InlineData("test.txt", "txt")] |
|||
[InlineData("test.TXT", "txt")] |
|||
public void Should_calculate_file_type(string fileName, string expected) |
|||
{ |
|||
var actual = fileName.FileType(); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("")] |
|||
[InlineData(" ")] |
|||
[InlineData(null)] |
|||
public void Should_blob_for_invalid_file_types(string fileName) |
|||
{ |
|||
var actual = fileName.FileType(); |
|||
|
|||
Assert.Equal("blob", actual); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue