11import fs from 'fs' ;
22import * as Path from 'path' ;
3+ import https from 'https' ;
4+ import http from 'http' ;
35import { ColumnProps , getEntityMeta , IEntity } from '../classes/index.js' ;
46import CoreEntity from '../classes/CoreEntity.js' ;
57import { Executable , ExecutableOptions } from './Executable.js' ;
@@ -15,6 +17,42 @@ export type XExecResult = {
1517 stdout : string ;
1618 stderr : string ;
1719} ;
20+ export const MineTypeMap = new Map < string , string > ( [
21+ [ 'text/html; charset=utf-8' , 'html' ] ,
22+ [ 'text/html' , 'html' ] ,
23+ [ 'text/plain' , 'txt' ] ,
24+ [ 'video/mp4' , 'mp4' ] ,
25+ [ 'video/mpeg' , 'mpeg' ] ,
26+ [ 'video/webm' , 'webm' ] ,
27+ [ 'audio/webm' , 'weba' ] ,
28+ [ 'audio/mpeg' , 'mp3' ] ,
29+ [ 'audio/wav' , 'wav' ] ,
30+ [ 'audio/aac' , 'aac' ] ,
31+ [ 'audio/webm' , 'aac' ] ,
32+ [ 'audio/opus' , 'opus' ] ,
33+ [ 'image/webp' , 'webp' ] ,
34+ [ 'image/png' , 'png' ] ,
35+ [ 'image/jpeg' , 'jpg' ] ,
36+ [ 'image/gif' , 'gif' ] ,
37+ [ 'image/webp' , 'webp' ] ,
38+ [ 'image/svg+xml' , 'svg' ] ,
39+ [ 'application/pdf' , 'pdf' ] ,
40+ [ 'application/zip' , 'zip' ] ,
41+ [ 'application/x-rar-compressed' , 'rar' ] ,
42+ [ 'application/x-7z-compressed' , '7z' ] ,
43+ [ 'application/x-tar' , 'tar' ] ,
44+ [ 'application/x-bzip2' , 'bz2' ] ,
45+ [ 'application/x-gzip' , 'gz' ] ,
46+ [ 'application/json; charset=utf-8' , 'json' ] ,
47+ ] ) ;
48+
49+ function selectClient ( url : string ) {
50+ if ( url . startsWith ( 'https' ) ) {
51+ return https ;
52+ }
53+ return http ;
54+ }
55+
1856export class XUtil {
1957 /*
2058 * TIME
@@ -206,4 +244,49 @@ export class XUtil {
206244 const exe = new Executable ( cmd , options ) ;
207245 return exe . run ( args ) ;
208246 }
247+
248+ static downloadFile (
249+ url : string ,
250+ path : string ,
251+ extMap = MineTypeMap ,
252+ ) : Promise < {
253+ name : string ;
254+ size : number ;
255+ type : string ;
256+ } | null > {
257+ return new Promise ( ( resolve ) => {
258+ try {
259+ selectClient ( url )
260+ . get ( url , ( res ) => {
261+ const raw = extMap . get ( res . headers [ 'content-type' ] as string ) ;
262+ const ext = raw || 'blob' ;
263+ const fName = `${ path } .${ ext } ` ;
264+ const file = fs . createWriteStream ( fName ) ;
265+ // A chunk of data has been received.
266+ res . on ( 'data' , ( chunk ) => {
267+ file . write ( chunk ) ;
268+ } ) ;
269+
270+ // The whole response has been received. Print out the result.
271+ res . on ( 'end' , ( ) => {
272+ const cl = res . headers [ 'content-length' ] ;
273+ const cli = parseInt ( cl as string , 10 ) ;
274+ file . close ( ) ;
275+ resolve ( {
276+ size : cli ,
277+ name : Path . basename ( fName ) ,
278+ type : res . headers [ 'content-type' ] || '' ,
279+ } ) ;
280+ } ) ;
281+ } )
282+ . on ( 'error' , ( err ) => {
283+ console . error ( `Error: ${ err . message } ` ) ;
284+ resolve ( null ) ;
285+ } ) ;
286+ } catch ( e ) {
287+ console . error ( e ) ;
288+ resolve ( null ) ;
289+ }
290+ } ) ;
291+ }
209292}
0 commit comments