Hochladen von Dateien mit flow.js + ng-flow WebAPI 2

Ich versuche zu verwenden flow.js (https://github.com/flowjs/flow.js) über seine Winkel-wrapper - ( https://github.com/flowjs/ng-flow/tree/master/samples/basic ) zum hochladen von Dateien zu einer ASP.NET WebAPI 2 server. Jedenfalls, wenn ich wählen Sie eine Datei zum hochladen meiner WebAPI bekommt nur der erste chunk GET-Anforderung und dann passiert nichts mehr: keine POST ist getan, und es scheint, dass flow.js nicht starten Sie den upload.

Die erste gefeuert, wenn ich eine Datei auszuwählen ist:

GET http://localhost:49330/api/upload?flowChunkNumber=1&flowChunkSize=1048576&flowCurrentChunkSize=4751&flowTotalSize=4751&flowIdentifier=4751-ElmahMySqlsql&flowFilename=Elmah.MySql.sql&flowRelativePath=Elmah.MySql.sql&flowTotalChunks=1 HTTP/1.1
Host: localhost:49330
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36
Accept: */*
Referer: http://localhost:49330/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6

... Und die Antwort ist:

HTTP/1.1 202 Accepted
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcUHJvamVjdHNcNDViXFRlc3RcVXBUZXN0XFVwVGVzdFxhcGlcdXBsb2Fk?=
X-Powered-By: ASP.NET
Date: Fri, 17 Apr 2015 08:02:56 GMT
Content-Length: 0

Dann keine Aufträge mehr erteilt werden.

Wie es scheint, gibt es keine up-to-date WebAPI Beispiel, aber nur vereinzelte Beiträge, die ich erstellt für Neulinge wie mich ein dummy-repro-Lösung, die Sie herunterladen können http://1drv.ms/1CSF5jq: es ist ein ASP.NET WebAPI 2 Lösung wo ich die upload-code in die home-Ansicht, nach dem hinzufügen der entsprechenden API-controller. Drücken Sie einfach die F5-Taste und versuchen Sie den Upload einer Datei. Finden Sie die API-controller in UploadController.cs.

Den relevanten code-Teile sind:

a) client-Seite: eine Seite ähnlich der quick-start-Beispiel der ng-flow-Seite:

<div class="row">
    <div class="col-md-12">
        <div flow-init="{target: '/api/upload'}"
             flow-files-submitted="$flow.upload()"
             flow-file-success="$file.msg = $message">
            <input type="file" flow-btn />
            <ol>
                <li ng-repeat="file in $flow.files">{{file.name}}: {{file.msg}}</li>
            </ol>
        </div>
    </div>
</div>

Der entsprechende code ist im wesentlichen ein leeres TS-Skelett mit der Modul-Initialisierung:

module Up {
    export interface IMainScope {
    }

    export class MainController {
        public static $inject = ["$scope"];
        constructor(private $scope: IMainScope) {
        }
    }

    var app = angular.module("app", ["flow"]);
    app.controller("mainController", MainController);
}

b) server-Seite: ich habe einige bunding für die erforderlichen Skripten, und die folgenden controller, modifiziert aus der Beispiel-code, den ich gefunden bei Wie zum hochladen von Datei in Blöcken in ASP.NET mit ng-Flow. Beachten Sie, dass in den GET - Upload Methode, die ich geändert, die Signatur mit einem binding-Modell (sonst würde man ein 404 als der Weg war nicht abgestimmt), und wenn der chunk nicht gefunden ich wieder ein 202 - Accepted - code anstatt 404, als flow.js die Dokumentation sagt, dass 200 entspricht "Das Stück wurde akzeptiert und korrekt. Keine Notwendigkeit, re-upload", während ein 404 bricht der ganze laden, und jedem anderen code (wie 202 hier) erzählt die uploader zu wiederholen.

[RoutePrefix("api")]
public class UploadController : ApiController
{
    private readonly string _sRoot;

    public UploadController()
    {
        _sRoot = HostingEnvironment.MapPath("~/App_Data/Uploads");
    }

    [Route("upload"), AcceptVerbs("GET")]
    public IHttpActionResult Upload([FromUri] UploadBindingModel model)
    {
        if (IsChunkHere(model.FlowChunkNumber, model.FlowIdentifier)) return Ok();
        return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Accepted));
    }

    [Route("upload"), AcceptVerbs("POST")]
    public async Task<IHttpActionResult> Upload()
    {
        //ensure that the request contains multipart/form-data
        if (!Request.Content.IsMimeMultipartContent())
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);

        if (!Directory.Exists(_sRoot)) Directory.CreateDirectory(_sRoot);
        MultipartFormDataStreamProvider provider = 
            new MultipartFormDataStreamProvider(_sRoot);
        try
        {
            await Request.Content.ReadAsMultipartAsync(provider);
            int nChunkNumber = Convert.ToInt32(provider.FormData["flowChunkNumber"]);
            int nTotalChunks = Convert.ToInt32(provider.FormData["flowTotalChunks"]);
            string sIdentifier = provider.FormData["flowIdentifier"];
            string sFileName = provider.FormData["flowFilename"];

            //rename the generated file
            MultipartFileData chunk = provider.FileData[0]; //Only one file in multipart message
            RenameChunk(chunk, nChunkNumber, sIdentifier);

            //assemble chunks into single file if they're all here
            TryAssembleFile(sIdentifier, nTotalChunks, sFileName);

            return Ok();
        }
        catch (Exception ex)
        {
            return InternalServerError(ex);
        }
    }

    private string GetChunkFileName(int chunkNumber, string identifier)
    {
        return Path.Combine(_sRoot,
            String.Format(CultureInfo.InvariantCulture, "{0}_{1}",
                identifier, chunkNumber));
    }

    private void RenameChunk(MultipartFileData chunk, int chunkNumber, string identifier)
    {
        string sGeneratedFileName = chunk.LocalFileName;
        string sChunkFileName = GetChunkFileName(chunkNumber, identifier);
        if (File.Exists(sChunkFileName)) File.Delete(sChunkFileName);
        File.Move(sGeneratedFileName, sChunkFileName);
    }

    private string GetFileName(string identifier)
    {
        return Path.Combine(_sRoot, identifier);
    }

    private bool IsChunkHere(int chunkNumber, string identifier)
    {
        string sFileName = GetChunkFileName(chunkNumber, identifier);
        return File.Exists(sFileName);
    }

    private bool AreAllChunksHere(string identifier, int totalChunks)
    {
        for (int nChunkNumber = 1; nChunkNumber <= totalChunks; nChunkNumber++)
            if (!IsChunkHere(nChunkNumber, identifier)) return false;
        return true;
    }

    private void TryAssembleFile(string identifier, int totalChunks, string filename)
    {
        if (!AreAllChunksHere(identifier, totalChunks)) return;

        //create a single file
        string sConsolidatedFileName = GetFileName(identifier);
        using (Stream destStream = File.Create(sConsolidatedFileName, 15000))
        {
            for (int nChunkNumber = 1; nChunkNumber <= totalChunks; nChunkNumber++)
            {
                string sChunkFileName = GetChunkFileName(nChunkNumber, identifier);
                using (Stream sourceStream = File.OpenRead(sChunkFileName))
                {
                    sourceStream.CopyTo(destStream);
                }
            } //efor
            destStream.Close();
        }

        //rename consolidated with original name of upload
        //strip to filename if directory is specified (avoid cross-directory attack)
        filename = Path.GetFileName(filename);
        Debug.Assert(filename != null);

        string sRealFileName = Path.Combine(_sRoot, filename);
        if (File.Exists(filename)) File.Delete(sRealFileName);
        File.Move(sConsolidatedFileName, sRealFileName);

        //delete chunk files
        for (int nChunkNumber = 1; nChunkNumber <= totalChunks; nChunkNumber++)
        {
            string sChunkFileName = GetChunkFileName(nChunkNumber, identifier);
            File.Delete(sChunkFileName);
        } //efor
    }
}
  • Ich muss hinzufügen, dass nach github.com/flowjs/ng-flow/issues/144 und scheinbar in Kontrast mit der Dokumentation, es scheint, 404, sollten zurückgegeben werden ERHALTEN, wenn der chunk nicht gefunden. Ich habe versucht, aber es ändert sich nichts und kein upload gestartet.
InformationsquelleAutor Naftis | 2015-04-17
Schreibe einen Kommentar