@@ -2,6 +2,7 @@ import _ from 'lodash';
22import { diffConvertYaml } from '@serverless-devs/diff' ;
33import inquirer from 'inquirer' ;
44import fs from 'fs' ;
5+ import os from 'os' ;
56import assert from 'assert' ;
67import path from 'path' ;
78import { yellow } from 'chalk' ;
@@ -21,6 +22,7 @@ import { ICredentials } from '@serverless-devs/component-interface';
2122import { calculateCRC64 , getFileSize , parseAutoConfig , checkFcDir } from '../../../utils' ;
2223import OSS from '../../../resources/oss' ;
2324import { setNodeModulesBinPermissions } from '../../../resources/fc/impl/utils' ;
25+ import downloads from '@serverless-devs/downloads' ;
2426
2527type IType = 'code' | 'config' | boolean ;
2628interface IOpts {
@@ -277,12 +279,18 @@ export default class Service extends Base {
277279 return true ;
278280 }
279281
280- let zipPath : string = path . isAbsolute ( codeUri )
281- ? codeUri
282- : path . join ( this . inputs . baseDir , codeUri ) ;
282+ let zipPath : string ;
283+ let downloadedTempDir = '' ;
284+ // 处理不同类型的 codeUri
285+ if ( codeUri . startsWith ( 'http://' ) || codeUri . startsWith ( 'https://' ) ) {
286+ zipPath = await this . _downloadFromUrl ( codeUri ) ;
287+ downloadedTempDir = path . dirname ( zipPath ) ;
288+ } else {
289+ zipPath = path . isAbsolute ( codeUri ) ? codeUri : path . join ( this . inputs . baseDir , codeUri ) ;
290+ }
283291 logger . debug ( `Code path absolute path: ${ zipPath } ` ) ;
284292
285- const needZip = this . _assertNeedZip ( codeUri ) ;
293+ const needZip = this . _assertNeedZip ( zipPath ) ;
286294 logger . debug ( `Need zip file: ${ needZip } ` ) ;
287295
288296 let generateZipFilePath = '' ;
@@ -330,9 +338,58 @@ export default class Service extends Base {
330338 }
331339 }
332340
341+ if ( downloadedTempDir ) {
342+ try {
343+ logger . debug ( `Removing temp download dir: ${ downloadedTempDir } ` ) ;
344+ fs . rmSync ( downloadedTempDir , { recursive : true , force : true } ) ;
345+ } catch ( ex ) {
346+ logger . debug ( `Unable to remove temp download dir: ${ downloadedTempDir } ` ) ;
347+ }
348+ }
349+
333350 return true ;
334351 }
335352
353+ /**
354+ * 从URL下载文件到本地临时目录
355+ */
356+ private async _downloadFromUrl ( url : string ) : Promise < string > {
357+ logger . info ( `Downloading code from URL: ${ url } ` ) ;
358+
359+ // 创建临时目录
360+ const tempDir = path . join ( os . tmpdir ( ) , 'fc_code_download' ) ;
361+ let downloadPath : string ;
362+
363+ try {
364+ // 从URL获取文件名
365+ const urlPath = new URL ( url ) . pathname ;
366+ const parsedPathName = path . parse ( urlPath ) . name ;
367+ const filename = path . basename ( urlPath ) || `downloaded_code_${ Date . now ( ) } ` ;
368+ downloadPath = path . join ( tempDir , filename ) ;
369+
370+ await downloads ( url , {
371+ dest : tempDir ,
372+ filename : parsedPathName ,
373+ extract : false ,
374+ } ) ;
375+
376+ logger . debug ( `Downloaded file to: ${ downloadPath } ` ) ;
377+
378+ // 返回下载文件路径,由主流程决定是否需要压缩
379+ return downloadPath ;
380+ } catch ( error ) {
381+ // 如果下载失败,清理临时目录
382+ try {
383+ fs . rmSync ( tempDir , { recursive : true , force : true } ) ;
384+ logger . debug ( `Cleaned up temporary directory after error: ${ tempDir } ` ) ;
385+ } catch ( cleanupError ) {
386+ logger . debug ( `Failed to clean up temporary directory: ${ cleanupError . message } ` ) ;
387+ }
388+
389+ throw new Error ( `Failed to download code from URL: ${ error . message } ` ) ;
390+ }
391+ }
392+
336393 /**
337394 * 生成 auto 资源,非 FC 资源,主要指 vpc、nas、log、role(oss mount 挂载点才有)
338395 */
0 commit comments