Created
June 17, 2022 13:45
-
-
Save tangb/f749af0f95a1db03cc1c0abf5a8ed03d to your computer and use it in GitHub Desktop.
My dropbox backend service (nestjs)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Dropbox, DropboxResponse, files as DropboxFiles, sharing } from 'dropbox'; | |
import { IFilesProvider, ProviderFileLink, FILE_MIME_DIRECTORY, ProviderFileUpload } from './files-providers.types'; | |
import mime from 'mime-types'; | |
import { AppLoggerService } from '../logger/app-logger.service'; | |
import 'isomorphic-fetch'; // fetch stuff for Dropbox | |
import { DropboxFile } from './dropbox-file.entity'; | |
import { Readable } from 'stream'; | |
import * as path from 'path'; | |
// eslint-disable-next-line @typescript-eslint/no-var-requires | |
const DropboxStream = require('dropbox-stream'); | |
interface IFilesListFolderResult { | |
files: DropboxFile[]; | |
cursor: string; | |
more: boolean; | |
} | |
export enum DROPBOX_CREATE_SHARED_LINK_ERRORS { | |
UNKNOWN = 0, | |
LINK_ALREADY_EXISTS, | |
ACCESS_DENIED, | |
EMAIL_NOT_VERIFIED, | |
SETTINGS_ERROR, | |
FILE_NOT_FOUND, | |
} | |
export enum DROPBOX_GET_SHARED_LINK_ERRORS { | |
UNKNOWN = 10, | |
CURSOR_RESET, | |
INVALID_FILE_PATH, | |
OTHER, | |
INVALID_TYPE, | |
NOT_FOUND, | |
TOO_MANY, | |
} | |
export enum DROPBOX_FILES_LIST_FOLDER_ERRORS { | |
UNKNOWN = 20, | |
CURSOR_RESET, | |
INVALID_FILE_PATH, | |
OTHER, | |
} | |
export enum DROPBOX_REVOKE_SHARED_LINK { | |
OK = 30, | |
UNKNOWN, | |
OTHER, | |
ACCESS_DENIED, | |
MALFORMED_URL, | |
NOT_FOUND, | |
UNSUPPORTED, | |
} | |
export enum DROPBOX_FILES_GET_METADATA { | |
UNKNOWN = 50, | |
NOT_FOUND, | |
ACCESS_DENIED, | |
INVALID, | |
CANT_ACCESS, | |
} | |
export class DropboxProvider extends IFilesProvider { | |
/** | |
* API documentation https://www.dropbox.com/developers/documentation/http/documentation | |
*/ | |
private dbx: Dropbox; | |
constructor( | |
public logger: AppLoggerService, | |
private readonly token: string, | |
private readonly baseDir: string, | |
private readonly linkVisibility: 'public' | 'team_only' | 'password', | |
) { | |
super(); | |
this.logger.debug(`Init Dropbox API with token "${token}"`); | |
this.dbx = new Dropbox({ | |
accessToken: token, | |
fetch, | |
}); | |
} | |
public async getFiles(processBatch: (files: DropboxFile[], batchNumber: number) => Promise<void>): Promise<void> { | |
try { | |
// let output: DropboxFile[] = []; | |
let filesCount = 0; | |
let batchNumber = 1; | |
// first batch | |
this.logger.debug('First batch'); | |
let result = await this.filesListFolder(); | |
this.logger.trace(` -> ${result.files.length} results`); | |
filesCount += result.files.length; | |
try { | |
await processBatch(result.files, batchNumber); | |
} catch (err) { | |
this.logger.error(' -> process batch failed: ', err); | |
} | |
this.logger.debug(` -> ${filesCount} files found`); | |
// more batch | |
while (result.more) { | |
batchNumber++; | |
this.logger.debug('Next batch'); | |
result = await this.filesListFolderContinue(result.cursor); | |
this.logger.trace(` -> ${result.files.length} results`); | |
try { | |
await processBatch(result.files, batchNumber); | |
} catch (err) { | |
this.logger.error(' -> process batch failed: ', err); | |
} | |
filesCount += result.files.length; | |
this.logger.debug(` -> ${filesCount} files found`); | |
} | |
} catch (error) { | |
this.logger.error('Unable to get Dropbox files', { error }); | |
throw error; | |
} | |
} | |
public async createFileLink(internalId: string): Promise<ProviderFileLink> { | |
const dropboxFilePath = await this.filesGetMetadata(internalId); | |
this.logger.debug('File metadata:', { dropboxFilePath }); | |
this.logger.debug(`Create file link for file "${internalId}" with path "${dropboxFilePath}"`); | |
return this.createSharedLinkWithSettings(dropboxFilePath, internalId); | |
} | |
public async getFileLink(internalId: string): Promise<ProviderFileLink> { | |
const dropboxFilePath = await this.filesGetMetadata(internalId); | |
this.logger.debug('File metadata:', { dropboxFilePath }); | |
this.logger.debug(`Get file link for file "${internalId}" with path "${dropboxFilePath}"`); | |
try { | |
const sharedLink = await this.listSharedLink(dropboxFilePath, internalId); | |
return sharedLink; | |
} catch(error) { | |
this.logger.warn('File seems not to have existing link', {internalId, error}); | |
} | |
return | |
} | |
public deleteFileLink(link: ProviderFileLink): Promise<boolean> { | |
this.logger.info(`Delete file link from Dropbox for url: ${link.url}`); | |
return this.revokeSharedLink(link.url); | |
} | |
... | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment