1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-25 10:43:13 +02:00

fix(web,server): use POST request to get download info (#3694)

* fix(web,server): use POST request to get download info

* chore: open api
This commit is contained in:
Jason Rasmussen 2023-08-15 11:49:32 -04:00 committed by GitHub
parent a75f368d5b
commit efc7fdb669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 190 additions and 207 deletions

View File

@ -1132,6 +1132,37 @@ export interface DownloadArchiveInfo {
*/
'size': number;
}
/**
*
* @export
* @interface DownloadInfoDto
*/
export interface DownloadInfoDto {
/**
*
* @type {string}
* @memberof DownloadInfoDto
*/
'albumId'?: string;
/**
*
* @type {number}
* @memberof DownloadInfoDto
*/
'archiveSize'?: number;
/**
*
* @type {Array<string>}
* @memberof DownloadInfoDto
*/
'assetIds'?: Array<string>;
/**
*
* @type {string}
* @memberof DownloadInfoDto
*/
'userId'?: string;
}
/**
*
* @export
@ -4880,7 +4911,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
downloadArchive: async (assetIdsDto: AssetIdsDto, key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'assetIdsDto' is not null or undefined
assertParamExists('downloadArchive', 'assetIdsDto', assetIdsDto)
const localVarPath = `/asset/download`;
const localVarPath = `/asset/download/archive`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
@ -5379,16 +5410,15 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
},
/**
*
* @param {Array<string>} [assetIds]
* @param {string} [albumId]
* @param {string} [userId]
* @param {number} [archiveSize]
* @param {DownloadInfoDto} downloadInfoDto
* @param {string} [key]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getDownloadInfo: async (assetIds?: Array<string>, albumId?: string, userId?: string, archiveSize?: number, key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/asset/download`;
getDownloadInfo: async (downloadInfoDto: DownloadInfoDto, key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'downloadInfoDto' is not null or undefined
assertParamExists('getDownloadInfo', 'downloadInfoDto', downloadInfoDto)
const localVarPath = `/asset/download/info`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
@ -5396,7 +5426,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
@ -5409,31 +5439,18 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
if (assetIds) {
localVarQueryParameter['assetIds'] = assetIds;
}
if (albumId !== undefined) {
localVarQueryParameter['albumId'] = albumId;
}
if (userId !== undefined) {
localVarQueryParameter['userId'] = userId;
}
if (archiveSize !== undefined) {
localVarQueryParameter['archiveSize'] = archiveSize;
}
if (key !== undefined) {
localVarQueryParameter['key'] = key;
}
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(downloadInfoDto, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
@ -6141,16 +6158,13 @@ export const AssetApiFp = function(configuration?: Configuration) {
},
/**
*
* @param {Array<string>} [assetIds]
* @param {string} [albumId]
* @param {string} [userId]
* @param {number} [archiveSize]
* @param {DownloadInfoDto} downloadInfoDto
* @param {string} [key]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getDownloadInfo(assetIds?: Array<string>, albumId?: string, userId?: string, archiveSize?: number, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<DownloadResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getDownloadInfo(assetIds, albumId, userId, archiveSize, key, options);
async getDownloadInfo(downloadInfoDto: DownloadInfoDto, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<DownloadResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getDownloadInfo(downloadInfoDto, key, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -6406,8 +6420,8 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest = {}, options?: AxiosRequestConfig): AxiosPromise<DownloadResponseDto> {
return localVarFp.getDownloadInfo(requestParameters.assetIds, requestParameters.albumId, requestParameters.userId, requestParameters.archiveSize, requestParameters.key, options).then((request) => request(axios, basePath));
getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest, options?: AxiosRequestConfig): AxiosPromise<DownloadResponseDto> {
return localVarFp.getDownloadInfo(requestParameters.downloadInfoDto, requestParameters.key, options).then((request) => request(axios, basePath));
},
/**
*
@ -6788,31 +6802,10 @@ export interface AssetApiGetByTimeBucketRequest {
export interface AssetApiGetDownloadInfoRequest {
/**
*
* @type {Array<string>}
* @type {DownloadInfoDto}
* @memberof AssetApiGetDownloadInfo
*/
readonly assetIds?: Array<string>
/**
*
* @type {string}
* @memberof AssetApiGetDownloadInfo
*/
readonly albumId?: string
/**
*
* @type {string}
* @memberof AssetApiGetDownloadInfo
*/
readonly userId?: string
/**
*
* @type {number}
* @memberof AssetApiGetDownloadInfo
*/
readonly archiveSize?: number
readonly downloadInfoDto: DownloadInfoDto
/**
*
@ -7281,8 +7274,8 @@ export class AssetApi extends BaseAPI {
* @throws {RequiredError}
* @memberof AssetApi
*/
public getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest = {}, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).getDownloadInfo(requestParameters.assetIds, requestParameters.albumId, requestParameters.userId, requestParameters.archiveSize, requestParameters.key, options).then((request) => request(this.axios, this.basePath));
public getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).getDownloadInfo(requestParameters.downloadInfoDto, requestParameters.key, options).then((request) => request(this.axios, this.basePath));
}
/**

View File

@ -45,6 +45,7 @@ doc/DeleteAssetDto.md
doc/DeleteAssetResponseDto.md
doc/DeleteAssetStatus.md
doc/DownloadArchiveInfo.md
doc/DownloadInfoDto.md
doc/DownloadResponseDto.md
doc/ExifResponseDto.md
doc/ImportAssetDto.md
@ -186,6 +187,7 @@ lib/model/delete_asset_dto.dart
lib/model/delete_asset_response_dto.dart
lib/model/delete_asset_status.dart
lib/model/download_archive_info.dart
lib/model/download_info_dto.dart
lib/model/download_response_dto.dart
lib/model/exif_response_dto.dart
lib/model/import_asset_dto.dart
@ -298,6 +300,7 @@ test/delete_asset_dto_test.dart
test/delete_asset_response_dto_test.dart
test/delete_asset_status_test.dart
test/download_archive_info_test.dart
test/download_info_dto_test.dart
test/download_response_dto_test.dart
test/exif_response_dto_test.dart
test/import_asset_dto_test.dart

BIN
mobile/openapi/README.md generated

Binary file not shown.

Binary file not shown.

BIN
mobile/openapi/doc/DownloadInfoDto.md generated Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1026,84 +1026,7 @@
]
}
},
"/asset/download": {
"get": {
"operationId": "getDownloadInfo",
"parameters": [
{
"name": "assetIds",
"required": false,
"in": "query",
"schema": {
"format": "uuid",
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name": "albumId",
"required": false,
"in": "query",
"schema": {
"format": "uuid",
"type": "string"
}
},
{
"name": "userId",
"required": false,
"in": "query",
"schema": {
"format": "uuid",
"type": "string"
}
},
{
"name": "archiveSize",
"required": false,
"in": "query",
"schema": {
"type": "number"
}
},
{
"name": "key",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DownloadResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Asset"
]
},
"/asset/download/archive": {
"post": {
"operationId": "downloadArchive",
"parameters": [
@ -1155,6 +1078,57 @@
]
}
},
"/asset/download/info": {
"post": {
"operationId": "getDownloadInfo",
"parameters": [
{
"name": "key",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DownloadInfoDto"
}
}
},
"required": true
},
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DownloadResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Asset"
]
}
},
"/asset/download/{id}": {
"post": {
"operationId": "downloadFile",
@ -5549,6 +5523,29 @@
],
"type": "object"
},
"DownloadInfoDto": {
"properties": {
"albumId": {
"format": "uuid",
"type": "string"
},
"archiveSize": {
"type": "integer"
},
"assetIds": {
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
},
"userId": {
"format": "uuid",
"type": "string"
}
},
"type": "object"
},
"DownloadResponseDto": {
"properties": {
"archives": {

View File

@ -13,7 +13,7 @@ import { IAssetRepository } from './asset.repository';
import {
AssetIdsDto,
DownloadArchiveInfo,
DownloadDto,
DownloadInfoDto,
DownloadResponseDto,
MemoryLaneDto,
TimeBucketAssetDto,
@ -176,7 +176,7 @@ export class AssetService {
return this.storageRepository.createReadStream(asset.originalPath, mimeTypes.lookup(asset.originalPath));
}
async getDownloadInfo(authUser: AuthUserDto, dto: DownloadDto): Promise<DownloadResponseDto> {
async getDownloadInfo(authUser: AuthUserDto, dto: DownloadInfoDto): Promise<DownloadResponseDto> {
const targetSize = dto.archiveSize || HumanReadableSize.GiB * 4;
const archives: DownloadArchiveInfo[] = [];
let archive: DownloadArchiveInfo = { size: 0, assetIds: [] };
@ -234,7 +234,7 @@ export class AssetService {
return { stream: zip.stream };
}
private async getDownloadAssets(authUser: AuthUserDto, dto: DownloadDto): Promise<AsyncGenerator<AssetEntity[]>> {
private async getDownloadAssets(authUser: AuthUserDto, dto: DownloadInfoDto): Promise<AsyncGenerator<AssetEntity[]>> {
const PAGINATION_SIZE = 2500;
if (dto.assetIds) {

View File

@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger';
import { IsInt, IsOptional, IsPositive } from 'class-validator';
import { ValidateUUID } from '../../domain.util';
export class DownloadDto {
export class DownloadInfoDto {
@ValidateUUID({ each: true, optional: true })
assetIds?: string[];
@ -15,6 +15,7 @@ export class DownloadDto {
@IsInt()
@IsPositive()
@IsOptional()
@ApiProperty({ type: 'integer' })
archiveSize?: number;
}

View File

@ -5,7 +5,7 @@ import {
AssetStatsDto,
AssetStatsResponseDto,
AuthUserDto,
DownloadDto,
DownloadInfoDto,
DownloadResponseDto,
MapMarkerResponseDto,
MemoryLaneDto,
@ -39,13 +39,13 @@ export class AssetController {
}
@SharedLinkRoute()
@Get('download')
getDownloadInfo(@AuthUser() authUser: AuthUserDto, @Query() dto: DownloadDto): Promise<DownloadResponseDto> {
@Post('download/info')
getDownloadInfo(@AuthUser() authUser: AuthUserDto, @Body() dto: DownloadInfoDto): Promise<DownloadResponseDto> {
return this.service.getDownloadInfo(authUser, dto);
}
@SharedLinkRoute()
@Post('download')
@Post('download/archive')
@HttpCode(HttpStatus.OK)
@ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
downloadArchive(@AuthUser() authUser: AuthUserDto, @Body() dto: AssetIdsDto): Promise<StreamableFile> {

View File

@ -1132,6 +1132,37 @@ export interface DownloadArchiveInfo {
*/
'size': number;
}
/**
*
* @export
* @interface DownloadInfoDto
*/
export interface DownloadInfoDto {
/**
*
* @type {string}
* @memberof DownloadInfoDto
*/
'albumId'?: string;
/**
*
* @type {number}
* @memberof DownloadInfoDto
*/
'archiveSize'?: number;
/**
*
* @type {Array<string>}
* @memberof DownloadInfoDto
*/
'assetIds'?: Array<string>;
/**
*
* @type {string}
* @memberof DownloadInfoDto
*/
'userId'?: string;
}
/**
*
* @export
@ -4880,7 +4911,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
downloadArchive: async (assetIdsDto: AssetIdsDto, key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'assetIdsDto' is not null or undefined
assertParamExists('downloadArchive', 'assetIdsDto', assetIdsDto)
const localVarPath = `/asset/download`;
const localVarPath = `/asset/download/archive`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
@ -5379,16 +5410,15 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
},
/**
*
* @param {Array<string>} [assetIds]
* @param {string} [albumId]
* @param {string} [userId]
* @param {number} [archiveSize]
* @param {DownloadInfoDto} downloadInfoDto
* @param {string} [key]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getDownloadInfo: async (assetIds?: Array<string>, albumId?: string, userId?: string, archiveSize?: number, key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/asset/download`;
getDownloadInfo: async (downloadInfoDto: DownloadInfoDto, key?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'downloadInfoDto' is not null or undefined
assertParamExists('getDownloadInfo', 'downloadInfoDto', downloadInfoDto)
const localVarPath = `/asset/download/info`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
@ -5396,7 +5426,7 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
@ -5409,31 +5439,18 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
if (assetIds) {
localVarQueryParameter['assetIds'] = assetIds;
}
if (albumId !== undefined) {
localVarQueryParameter['albumId'] = albumId;
}
if (userId !== undefined) {
localVarQueryParameter['userId'] = userId;
}
if (archiveSize !== undefined) {
localVarQueryParameter['archiveSize'] = archiveSize;
}
if (key !== undefined) {
localVarQueryParameter['key'] = key;
}
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(downloadInfoDto, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
@ -6141,16 +6158,13 @@ export const AssetApiFp = function(configuration?: Configuration) {
},
/**
*
* @param {Array<string>} [assetIds]
* @param {string} [albumId]
* @param {string} [userId]
* @param {number} [archiveSize]
* @param {DownloadInfoDto} downloadInfoDto
* @param {string} [key]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getDownloadInfo(assetIds?: Array<string>, albumId?: string, userId?: string, archiveSize?: number, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<DownloadResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getDownloadInfo(assetIds, albumId, userId, archiveSize, key, options);
async getDownloadInfo(downloadInfoDto: DownloadInfoDto, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<DownloadResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getDownloadInfo(downloadInfoDto, key, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@ -6406,8 +6420,8 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest = {}, options?: AxiosRequestConfig): AxiosPromise<DownloadResponseDto> {
return localVarFp.getDownloadInfo(requestParameters.assetIds, requestParameters.albumId, requestParameters.userId, requestParameters.archiveSize, requestParameters.key, options).then((request) => request(axios, basePath));
getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest, options?: AxiosRequestConfig): AxiosPromise<DownloadResponseDto> {
return localVarFp.getDownloadInfo(requestParameters.downloadInfoDto, requestParameters.key, options).then((request) => request(axios, basePath));
},
/**
*
@ -6788,31 +6802,10 @@ export interface AssetApiGetByTimeBucketRequest {
export interface AssetApiGetDownloadInfoRequest {
/**
*
* @type {Array<string>}
* @type {DownloadInfoDto}
* @memberof AssetApiGetDownloadInfo
*/
readonly assetIds?: Array<string>
/**
*
* @type {string}
* @memberof AssetApiGetDownloadInfo
*/
readonly albumId?: string
/**
*
* @type {string}
* @memberof AssetApiGetDownloadInfo
*/
readonly userId?: string
/**
*
* @type {number}
* @memberof AssetApiGetDownloadInfo
*/
readonly archiveSize?: number
readonly downloadInfoDto: DownloadInfoDto
/**
*
@ -7281,8 +7274,8 @@ export class AssetApi extends BaseAPI {
* @throws {RequiredError}
* @memberof AssetApi
*/
public getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest = {}, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).getDownloadInfo(requestParameters.assetIds, requestParameters.albumId, requestParameters.userId, requestParameters.archiveSize, requestParameters.key, options).then((request) => request(this.axios, this.basePath));
public getDownloadInfo(requestParameters: AssetApiGetDownloadInfoRequest, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).getDownloadInfo(requestParameters.downloadInfoDto, requestParameters.key, options).then((request) => request(this.axios, this.basePath));
}
/**

View File

@ -1,6 +1,6 @@
import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification';
import { downloadManager } from '$lib/stores/download';
import { api, AssetApiGetDownloadInfoRequest, BulkIdResponseDto, AssetResponseDto, DownloadResponseDto } from '@api';
import { api, BulkIdResponseDto, AssetResponseDto, DownloadResponseDto, DownloadInfoDto } from '@api';
import { handleError } from './handle-error';
export const addAssetsToAlbum = async (
@ -32,15 +32,11 @@ const downloadBlob = (data: Blob, filename: string) => {
URL.revokeObjectURL(url);
};
export const downloadArchive = async (
fileName: string,
options: Omit<AssetApiGetDownloadInfoRequest, 'key'>,
key?: string,
) => {
export const downloadArchive = async (fileName: string, options: DownloadInfoDto, key?: string) => {
let downloadInfo: DownloadResponseDto | null = null;
try {
const { data } = await api.assetApi.getDownloadInfo({ ...options, key });
const { data } = await api.assetApi.getDownloadInfo({ downloadInfoDto: options, key });
downloadInfo = data;
} catch (error) {
handleError(error, 'Unable to download files');