107 lines
2.6 KiB
TypeScript
107 lines
2.6 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Delete,
|
|
Get,
|
|
Param,
|
|
Post,
|
|
Query,
|
|
Res,
|
|
StreamableFile,
|
|
UseGuards,
|
|
} from "@nestjs/common";
|
|
import { SkipThrottle } from "@nestjs/throttler";
|
|
import * as contentDisposition from "content-disposition";
|
|
import { Response } from "express";
|
|
import { CreateShareGuard } from "src/share/guard/createShare.guard";
|
|
import { ShareOwnerGuard } from "src/share/guard/shareOwner.guard";
|
|
import { FileService } from "./file.service";
|
|
import { FileSecurityGuard } from "./guard/fileSecurity.guard";
|
|
import * as mime from "mime-types";
|
|
|
|
@Controller("shares/:shareId/files")
|
|
export class FileController {
|
|
constructor(private fileService: FileService) {}
|
|
|
|
@Post()
|
|
@SkipThrottle()
|
|
@UseGuards(CreateShareGuard, ShareOwnerGuard)
|
|
async create(
|
|
@Query()
|
|
query: {
|
|
id: string;
|
|
name: string;
|
|
chunkIndex: string;
|
|
totalChunks: string;
|
|
},
|
|
@Body() body: string,
|
|
@Param("shareId") shareId: string,
|
|
) {
|
|
const { id, name, chunkIndex, totalChunks } = query;
|
|
|
|
// Data can be empty if the file is empty
|
|
return await this.fileService.create(
|
|
body,
|
|
{ index: parseInt(chunkIndex), total: parseInt(totalChunks) },
|
|
{ id, name },
|
|
shareId,
|
|
);
|
|
}
|
|
|
|
@Get("zip")
|
|
@UseGuards(FileSecurityGuard)
|
|
async getZip(
|
|
@Res({ passthrough: true }) res: Response,
|
|
@Param("shareId") shareId: string,
|
|
) {
|
|
const zipStream = this.fileService.getZip(shareId);
|
|
|
|
res.set({
|
|
"Content-Type": "application/zip",
|
|
"Content-Disposition": contentDisposition(`${shareId}.zip`),
|
|
});
|
|
|
|
return new StreamableFile(zipStream);
|
|
}
|
|
|
|
@Get(":fileId")
|
|
@UseGuards(FileSecurityGuard)
|
|
async getFile(
|
|
@Res({ passthrough: true }) res: Response,
|
|
@Param("shareId") shareId: string,
|
|
@Param("fileId") fileId: string,
|
|
@Query("download") download = "true",
|
|
) {
|
|
const file = await this.fileService.get(shareId, fileId);
|
|
|
|
const headers = {
|
|
"Content-Type":
|
|
mime?.lookup?.(file.metaData.name) || "application/octet-stream",
|
|
"Content-Length": file.metaData.size,
|
|
"Content-Security-Policy": "script-src 'none'",
|
|
};
|
|
|
|
if (download === "true") {
|
|
headers["Content-Disposition"] = contentDisposition(file.metaData.name);
|
|
} else {
|
|
headers["Content-Disposition"] = contentDisposition(file.metaData.name, {
|
|
type: "inline",
|
|
});
|
|
}
|
|
|
|
res.set(headers);
|
|
|
|
return new StreamableFile(file.file);
|
|
}
|
|
|
|
@Delete(":fileId")
|
|
@SkipThrottle()
|
|
@UseGuards(ShareOwnerGuard)
|
|
async remove(
|
|
@Param("fileId") fileId: string,
|
|
@Param("shareId") shareId: string,
|
|
) {
|
|
await this.fileService.remove(shareId, fileId);
|
|
}
|
|
}
|