@@ -44,7 +44,7 @@ const getDefaultThumbPath = (mime) => {
4444} ;
4545
4646// 处理文件上传
47- router . post ( "/upload " , async ( ctx ) => {
47+ router . post ( "/files " , async ( ctx ) => {
4848 try {
4949 const files = ctx . request . files . file ;
5050 const fileList = Array . isArray ( files ) ? files : [ files ] ;
@@ -83,7 +83,7 @@ router.post("/upload", async (ctx) => {
8383 }
8484 }
8585
86- const fileUrl = `${ process . env . PUBLIC_NETWORK_DOMAIN } /files/${ fileId } ` ;
86+ const fileUrl = `${ process . env . PUBLIC_NETWORK_DOMAIN } /files/${ fileId } /preview ` ;
8787 const thumbUrl = shouldGenerateThumb ? `${ fileUrl } ?type=thumb` : null ;
8888
8989 await File . create ( {
@@ -118,7 +118,7 @@ router.post("/upload", async (ctx) => {
118118 await fsp . unlink ( file . filepath ) ;
119119 }
120120 }
121-
121+ ctx . status ( 201 ) ;
122122 ctx . body = fileList . length > 1 ? responses : responses [ 0 ] ;
123123 } catch ( error ) {
124124 ctx . status = 500 ;
@@ -198,6 +198,56 @@ router.get("/files", async (ctx) => {
198198// 获取单个文件信息
199199router . get ( "/files/:id" , async ( ctx ) => {
200200 const { id } = ctx . params ;
201+
202+ try {
203+ const file = await File . findOne ( {
204+ where : {
205+ id,
206+ is_delete : false ,
207+ is_public : true ,
208+ [ Op . or ] : [
209+ { public_expiration : null } ,
210+ { public_expiration : { [ Op . gt ] : new Date ( ) } } ,
211+ ] ,
212+ } ,
213+ attributes : [
214+ "id" ,
215+ "filename" ,
216+ "is_delete" ,
217+ "is_public" ,
218+ "public_expiration" ,
219+ "is_thumb" ,
220+ "filesize" ,
221+ "filelocation" ,
222+ "thumb_location" ,
223+ "mime" ,
224+ "ext" ,
225+ "created_at" ,
226+ "created_by" ,
227+ "updated_at" ,
228+ "updated_by" ,
229+ ] ,
230+ } ) ;
231+
232+ if ( ! file ) {
233+ ctx . status = 404 ;
234+ ctx . body = { message : "File not found or not accessible" } ;
235+ return ;
236+ }
237+
238+ ctx . body = file ;
239+
240+ // 返回文件流
241+ } catch ( error ) {
242+ ctx . status = 500 ;
243+ ctx . body = { message : "Internal server error" , error : error . message } ;
244+ console . error ( "Get file error:" , error ) ;
245+ }
246+ } ) ;
247+
248+ // 文件预览
249+ router . get ( "/files/:id/preview" , async ( ctx ) => {
250+ const { id } = ctx . params ;
201251 const { type } = ctx . query ; // 获取查询参数 'type',可以是 'thumb' 或 'original'
202252
203253 try {
@@ -259,7 +309,60 @@ router.get("/files/:id", async (ctx) => {
259309 }
260310} ) ;
261311
262- router . get ( "/files:export" , async ( ctx ) => {
312+ // 单文件下载
313+ router . get ( "/files/:id/export" , async ( ctx ) => {
314+ const { id } = ctx . params ;
315+
316+ try {
317+ const file = await File . findOne ( {
318+ where : {
319+ id : id ,
320+ is_delete : false ,
321+ [ Op . or ] : [
322+ { public_expiration : null } ,
323+ { public_expiration : { [ Op . gt ] : new Date ( ) } } ,
324+ ] ,
325+ } ,
326+ attributes : [ "filename" , "real_file_location" , "ext" ] ,
327+ } ) ;
328+
329+ if ( ! file ) {
330+ ctx . status = 404 ;
331+ ctx . body = { message : "No valid files found for the provided id" } ;
332+ return ;
333+ }
334+ // 单文件下载
335+ const filePath = file . real_file_location ;
336+ const fileName = file . filename ;
337+
338+ // 检查文件是否存在
339+ try {
340+ await fsp . access ( filePath ) ;
341+ } catch ( err ) {
342+ ctx . status = 404 ;
343+ ctx . body = { message : "File not found" } ;
344+ return ;
345+ }
346+ const { mime } = await detectFileType ( filePath ) ;
347+
348+ // 设置响应头
349+ ctx . set ( "Content-Type" , mime ) ;
350+ ctx . set ( "Content-Disposition" , `attachment; filename="${ fileName } "` ) ;
351+
352+ // 返回文件流
353+ ctx . body = fs . createReadStream ( filePath ) ;
354+ } catch ( error ) {
355+ ctx . status = 500 ;
356+ ctx . body = {
357+ message : "Error processing your download request" ,
358+ error : error . message ,
359+ } ;
360+ console . error ( "Download error:" , error ) ;
361+ }
362+ } ) ;
363+
364+ // 批量下载
365+ router . get ( "/files/export" , async ( ctx ) => {
263366 const fileIds = ctx . query . ids ? ctx . query . ids . split ( "," ) : [ ] ;
264367
265368 if ( fileIds . length === 0 ) {
0 commit comments