Function points:
1. implementing file uploads using. NET Core 2.0
2. Using Webuploader to achieve single file, multi-file upload
3. Use Webuploader to achieve multipart upload of large files.
4. Use Webuploader and Fastdfs for file upload.
5. The local file storage can be easily switched to Fastdfs via dependency injection
Main functions:
Directly on the code:
1. implementing file uploads using. NET Core 2.0
Publicactionresult Upload (iformcollection files) {varresult =NewUploadresult (); foreach(varIteminchfiles. Files) {#regionTurn a file into a byte streambyte[] buffer =New byte[item. Length]; Stream FS=item. Openreadstream (); Fs. Read (Buffer,0, buffer. Length); #endregionuploadconfig config=NewUploadconfig {Buffer=Buffer, FileName=item. FileName, Chunked= files. Keys.contains ("Chunk"), Previosname= files["Previosname"] }; Result=_provider. Upload (config); } returnJson (Result); }
Note here that the parameters, using Iformcollection, do not use Iformfile, using the latter, you cannot receive custom parameters sent by the foreground. Although I used the Fforeach loop, but the implementation of its files count only one, regardless of whether the foreground is sent a file, or a number of files, this should be studied, is not configured.
Private ReadOnly ifilesystemprovider _provider; Public HomeController (Ifilesystemprovider provider) { = provider; }
Ifilesystemprovider is defined as an interface, with local file storage, and distributed file storage implemented in two ways, followed by code.
2. Using Webuploader to achieve single file, multi-file upload
Here the main front code:
//instantiation ofuploader =webuploader.create ({pick: {ID:' #filePicker ', Label:' Click to select File '}, DND:' #dndArea ', paste:' #uploader ', swf: ' lib/webuploader/uploader.swf ', chunked:true,//Shard processing Large FilesCHUNKSIZE:1 * 1024 * 1024, Server:home/upload, Disableglobaldnd:true, Threads:1,//Upload concurrency numberfilenumlimit:300, Compress:false,//images are not compressed until they are uploadedFILESIZELIMIT:1024 * 1024 * 1024,//1024x768 MFILESINGLESIZELIMIT:1024 * 1024 * 1024//1024x768 M});
Initialize Webuploader here to pay attention to threads I think is 1, if the multipart upload, several segments simultaneously sent, the background if the write is a problem, especially the use of Fastdfs, the. NET version of the SDK does not support the ability to specify location write.
Notice an event: It is the weight of the multipart upload
function (file, response) { if (file.chunk + 1!== file.chunks) { $.extend ( Uploader.options.formData, {previosName:response.filePath}); Else { "" }); } return true ; });
Here's a little bit of explanation. See the Internet about the file multipart upload, are on the server side with temporary files to record the file upload address, when there is segmented information arrives, will query temporary files, take out the file address, and then to this address append file stream.
This increases the server-side complexity, and if it is distributed deployment, there will be a problem finding temporary files, which will take into account the database and distributed cache solutions, more complex.
Here is a brief explanation of the solution:
1) Backstage: After the first paragraph is successfully uploaded, the file address is returned. such as the return Json (result) of the Code;
2) Front desk: Use the Uploadaccept event to receive file information and back-office return addresses.
3) Front desk: In uploadaccept event: Add the parameter sent by the backend Previosname: the first paragraph returns the file address.
Note here that if multiple files are uploaded, the first fragment of the second file cannot have the upload address of the first file, as shown in the code above
4) Backstage: As the above code shows, receive the file address sent by the foreground, do the file append, you can.
3. Use Webuploader to achieve multipart upload of large files.
The following is the service-side code:
Publicuploadresult Upload (uploadconfig config) {//relative Path stringPath =getfilename (config); //creates a new file based on the path and writes bytes at the specified location, appended if the file already exists using(FileStream fs =File.openwrite (Path.Combine (_option. Rootfilepath, Path)) {if(fs. CanWrite) {fs. Seek (fs. Length, seekorigin.current); Fs. Write (config. Buffer,0, CONFIG. Buffer.length); Fs. Flush (); Fs. Close (); } } return NewUploadresult {FilePath = path, Originalname =CONFIG. FileName}; } Private stringgetfilename (uploadconfig config) {stringpath; if(string. IsNullOrEmpty (config. Previosname)) {path= Path.Combine (subdirectory, $"{guidto16string ()}. {CONFIG. FileName}");//returns the relative path and file nameChecksavepath (); } Else{Path=CONFIG. Previosname; if(string. IsNullOrEmpty (config. Previosname)) {Throw NewArgumentNullException ("The Previosname parameter cannot be empty"); } } returnpath; } Private stringChecksavepath () {varPath =Path.Combine (_option. Rootfilepath, subdirectory); //How to create a file path if the path does not exist if(!directory.exists (path)) {directory.createdirectory (path); } returnpath; }
Here's a look at the GetFileName method: The code is simple and does not explain.
4. Uploading files using Webuploader and Fastdfs
The code for the front-end code and the service-side action is the same. The main way to write files is different, the main code is as follows:
Publicuploadresult Upload (uploadconfig config) {if(string. IsNullOrEmpty (config. Previosname)) {varFileName =string. Empty; varStoragenode =_client. Getstoragenode (config. GroupName); if(!CONFIG. Chunked) {FileName=_client. UploadFile (storagenode, config. Buffer, path.getextension (config. FileName)); } Else { //multipart uploads need to call this methodFileName =_client. Uploadappenderfile (storagenode, config. Buffer, path.getextension (config. FileName)); } return NewUploadresult {FilePath = fileName, Originalname =CONFIG. FileName}; } Else { //multipart upload: need to provide upload groupname, file upload address previosname, file upload content filebody//Renew address config. Previosname_client. AppendFile (config. GroupName, CONFIG. Previosname, CONFIG. Buffer); return NewUploadresult {FilePath = config. Previosname, Originalname =CONFIG. FileName}; } }
Here note the multipart upload file, the first upload using the method is Uploadappenderfile, followed by the use of appendfile.
The code for connecting Fastdfs is as follows:
Public classFastdfsclientprovider:ifastdfsclientprovider {Private ReadOnlyfastdfsoption _options; Publicfastdfsclientprovider (fastdfsoption options) {_options=options; } Publicfastdfsclient getclient () {return NewFastdfsclient (NewList<ipendpoint> { NewIPEndPoint (Ipaddress.parse (_options. IpAddress), _options. Port)}); } }
5. The local file storage can be easily switched to Fastdfs via dependency injection
The code is as follows:
Public voidconfigureservices (iservicecollection services) {services. Addmvc (); Services. AddTransient<IFileSystemProvider> (m=>{ihostingenvironment env= m.getservice<ihostingenvironment>(); Localfsoption loption=Newlocalfsoption {Rootfilepath= Path.Combine (env. Contentrootpath,"Files") }; return NewLocalfsprovider (loption); }); }
If you want to change the implementation of a return to new Localfsprovider (loption), configure the parameters on the line.
Some code reference Bo friends, can not find the source, please cool solution.
ASP. NET Core 2.0 webuploader Fastdfs file upload multipart upload