1- using Microsoft . AspNetCore . Mvc ;
1+ using System . IO . Compression ;
2+ using MaiChartManager . Attributes ;
3+ using Microsoft . AspNetCore . Mvc ;
4+ using Microsoft . AspNetCore . WebUtilities ;
5+ using Microsoft . Net . Http . Headers ;
26using Microsoft . VisualBasic . FileIO ;
37
48namespace MaiChartManager . Controllers ;
59
610[ ApiController ]
711[ Route ( "MaiChartManagerServlet/[action]Api" ) ]
8- public class AssetDirController ( StaticSettings settings , ILogger < AssetDirController > logger )
12+ public class AssetDirController ( StaticSettings settings , ILogger < AssetDirController > logger ) : ControllerBase
913{
1014 [ HttpPost ]
1115 public void CreateAssetDir ( [ FromBody ] string dir )
@@ -32,7 +36,7 @@ public record GetAssetDirTxtValueRequest(string DirName, string FileName);
3236 [ HttpPost ]
3337 public string GetAssetDirTxtValue ( [ FromBody ] GetAssetDirTxtValueRequest req )
3438 {
35- return File . ReadAllText ( Path . Combine ( StaticSettings . StreamingAssets , req . DirName , req . FileName ) ) ;
39+ return System . IO . File . ReadAllText ( Path . Combine ( StaticSettings . StreamingAssets , req . DirName , req . FileName ) ) ;
3640 }
3741
3842 [ HttpDelete ]
@@ -46,7 +50,7 @@ public record PutAssetDirTxtValueRequest(string DirName, string FileName, string
4650 [ HttpPut ]
4751 public void PutAssetDirTxtValue ( [ FromBody ] PutAssetDirTxtValueRequest req )
4852 {
49- File . WriteAllText ( Path . Combine ( StaticSettings . StreamingAssets , req . DirName , req . FileName ) , req . Content ) ;
53+ System . IO . File . WriteAllText ( Path . Combine ( StaticSettings . StreamingAssets , req . DirName , req . FileName ) , req . Content ) ;
5054 }
5155
5256 [ HttpPost ]
@@ -75,35 +79,70 @@ public void RequestLocalImportDir()
7579
7680 if ( ! StaticSettings . ADirRegex ( ) . IsMatch ( destName ) || StaticSettings . AssetsDirs . Contains ( destName ) )
7781 {
78- var id = 0 ;
79- // 找到下一个未被使用的名称
80- foreach ( var dir in StaticSettings . AssetsDirs )
81- {
82- var strId = StaticSettings . ADirRegex ( ) . Match ( dir ) . Groups [ 1 ] . Value ;
83- var num = int . Parse ( strId ) ;
84- if ( num > id ) id = num ;
85- }
82+ destName = settings . GetFreeAssetDir ( ) ;
83+ }
84+
85+ var dest = Path . Combine ( StaticSettings . StreamingAssets , destName ) ;
86+ logger . LogInformation ( "Src: {src} Dest: {dest}" , src , dest ) ;
87+ FileSystem . CopyDirectory ( src , dest , UIOption . AllDialogs ) ;
88+ settings . ScanGenre ( ) ;
89+ settings . ScanVersionList ( ) ;
90+ settings . ScanAssetBundles ( ) ;
91+ settings . ScanSoundData ( ) ;
92+ settings . ScanMovieData ( ) ;
93+ }
94+
95+ public record UploadAssetDirResult ( string DirName ) ;
8696
87- id ++ ;
88- if ( id > 999 )
97+ [ HttpPost ]
98+ // https://code-maze.com/aspnetcore-upload-large-files/
99+ [ DisableRequestSizeLimit ]
100+ [ DisableFormValueModelBinding ]
101+ [ Route ( "{destName}" ) ]
102+ // 看起来就算用 IAsyncEnumerable 获取文件,还是会等所以文件都上传完了再调用这个方法
103+ // 而且不知道为什么上传到一半会 Network Error
104+ public async Task < UploadAssetDirResult > UploadAssetDir ( string ? destName )
105+ {
106+ logger . LogInformation ( "UploadAssetDir" ) ;
107+
108+ if ( destName is null || ! StaticSettings . ADirRegex ( ) . IsMatch ( destName ) || StaticSettings . AssetsDirs . Contains ( destName ) )
109+ {
110+ destName = settings . GetFreeAssetDir ( ) ;
111+ }
112+
113+ var dest = Path . Combine ( StaticSettings . StreamingAssets , destName ) ;
114+
115+ // https://stackoverflow.com/questions/36437282/dealing-with-large-file-uploads-on-asp-net-core-1-0
116+ var boundary = HeaderUtilities . RemoveQuotes ( MediaTypeHeaderValue . Parse ( Request . ContentType ) . Boundary ) . Value ;
117+ var reader = new MultipartReader ( boundary ! , Request . Body ) ;
118+ var section = await reader . ReadNextSectionAsync ( ) ;
119+
120+ while ( section != null )
121+ {
122+ if ( ContentDispositionHeaderValue . TryParse ( section . ContentDisposition , out var contentDisposition ) )
89123 {
90- id = 999 ;
91- while ( StaticSettings . AssetsDirs . Contains ( $ "A{ id : 000} ") )
124+ if ( contentDisposition . DispositionType . Equals ( "form-data" ) && ! string . IsNullOrEmpty ( contentDisposition . FileName . Value ) )
92125 {
93- id -- ;
126+ var fileName = contentDisposition . FileName . Value ;
127+ await using var stream = section . Body ;
128+ // 处理文件流
129+ logger . LogInformation ( "UploadAssetDir: {destName} {file}" , destName , fileName ) ;
130+ var filePath = Path . Combine ( dest , fileName . TrimStart ( '/' , '\\ ' ) ) ;
131+ Directory . CreateDirectory ( Path . GetDirectoryName ( filePath ) ) ;
132+ await using var fileStream = new FileStream ( filePath , FileMode . Create ) ;
133+ await stream . CopyToAsync ( fileStream ) ;
94134 }
95135 }
96136
97- destName = $ "A { id : 000 } " ;
137+ section = await reader . ReadNextSectionAsync ( ) ;
98138 }
99139
100- var dest = Path . Combine ( StaticSettings . StreamingAssets , destName ) ;
101- logger . LogInformation ( "Src: {src} Dest: {dest}" , src , dest ) ;
102- FileSystem . CopyDirectory ( src , dest , UIOption . AllDialogs ) ;
103140 settings . ScanGenre ( ) ;
104141 settings . ScanVersionList ( ) ;
105142 settings . ScanAssetBundles ( ) ;
106143 settings . ScanSoundData ( ) ;
107144 settings . ScanMovieData ( ) ;
145+
146+ return new UploadAssetDirResult ( destName ) ;
108147 }
109148}
0 commit comments