Browse Source

fix(cli): upload large file (#5242)

* fix(cli): upload large file

* fix: use known configuration

* chore: version bump

* chore: fix repo url

* fix conflict

---------

Co-authored-by: Jonathan Jogenfors <jonathan@jogenfors.se>
Alex 1 year ago
parent
commit
c8aa782fef
2 changed files with 39 additions and 6 deletions
  1. 24 1
      cli/src/commands/upload.ts
  2. 15 5
      cli/src/cores/models/asset.ts

+ 24 - 1
cli/src/commands/upload.ts

@@ -6,6 +6,8 @@ import { CrawlOptionsDto } from '../cores/dto/crawl-options-dto';
 import cliProgress from 'cli-progress';
 import byteSize from 'byte-size';
 import { BaseCommand } from '../cli/base-command';
+import axios, { AxiosRequestConfig } from 'axios';
+import FormData from 'form-data';
 
 export default class Upload extends BaseCommand {
   uploadLength!: number;
@@ -75,7 +77,8 @@ export default class Upload extends BaseCommand {
 
         if (!skipUpload) {
           if (!options.dryRun) {
-            const res = await this.immichApi.assetApi.uploadFile(asset.getUploadFileRequest());
+            const formData = asset.getUploadFormData();
+            const res = await this.uploadAsset(formData);
 
             if (options.album && asset.albumName) {
               let album = existingAlbums.find((album) => album.albumName === asset.albumName);
@@ -134,4 +137,24 @@ export default class Upload extends BaseCommand {
       }
     }
   }
+
+  private async uploadAsset(data: FormData): Promise<axios.AxiosResponse> {
+    const url = this.immichApi.apiConfiguration.instanceUrl + '/asset/upload';
+
+    const config: AxiosRequestConfig = {
+      method: 'post',
+      maxRedirects: 0,
+      url,
+      headers: {
+        'x-api-key': this.immichApi.apiConfiguration.apiKey,
+        ...data.getHeaders(),
+      },
+      maxContentLength: Infinity,
+      maxBodyLength: Infinity,
+      data,
+    };
+
+    const res = await axios(config);
+    return res;
+  }
 }

+ 15 - 5
cli/src/cores/models/asset.ts

@@ -1,8 +1,8 @@
 import * as fs from 'fs';
 import { basename } from 'node:path';
 import crypto from 'crypto';
-import { AssetApiUploadFileRequest } from 'src/api/open-api';
 import Os from 'os';
+import FormData from 'form-data';
 
 export class Asset {
   readonly path: string;
@@ -40,22 +40,32 @@ export class Asset {
     } catch (error) {}
   }
 
-  getUploadFileRequest(): AssetApiUploadFileRequest {
+  getUploadFormData(): FormData {
     if (!this.assetData) throw new Error('Asset data not set');
     if (!this.deviceAssetId) throw new Error('Device asset id not set');
     if (!this.fileCreatedAt) throw new Error('File created at not set');
     if (!this.fileModifiedAt) throw new Error('File modified at not set');
     if (!this.deviceId) throw new Error('Device id not set');
 
-    return {
+    const data: any = {
       assetData: this.assetData as any,
       deviceAssetId: this.deviceAssetId,
       deviceId: this.deviceId,
       fileCreatedAt: this.fileCreatedAt,
       fileModifiedAt: this.fileModifiedAt,
-      isFavorite: false,
-      sidecarData: this.sidecarData as any,
+      isFavorite: String(false),
     };
+    const formData = new FormData();
+
+    for (const prop in data) {
+      formData.append(prop, data[prop]);
+    }
+
+    if (this.sidecarData) {
+      formData.append('sidecarData', this.sidecarData);
+    }
+
+    return formData;
   }
 
   private getReadStream(path: string): fs.ReadStream {