Heim  >  Artikel  >  php教程  >  Der jQuery-Webuploader lädt große Dateien in Teilen hoch

Der jQuery-Webuploader lädt große Dateien in Teilen hoch

高洛峰
高洛峰Original
2016-12-07 14:19:383021Durchsuche

Im Allgemeinen werden beim Hochladen von Dateien die hochzuladenden Dateien über den Client auf den Server hochgeladen. Zu diesem Zeitpunkt befinden sich alle hochgeladenen Dateien im Serverspeicher Sehr eng, und im Allgemeinen verwenden wir Flash oder HTML5 für den asynchronen Upload. Auch wenn der Client anzeigt, dass die Datei zu 100 % hochgeladen wurde, dauert es immer noch lange, bis die aktuelle Seite angefordert wird Der Server wird ebenfalls blockiert.

Unter normalen Umständen wird es nach Abschluss der langen Übertragung normalerweise direkt auf dem Server gespeichert.

public void ProcessRequest(HttpContext context)
  {
   context.Response.ContentType = "text/plain";
   //保存文件
   context.Request.Files[0].SaveAs(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName));
   context.Response.Write("Hello World");
  }

In einem aktuellen Projekt wurde Baidus Open-Source-Upload-Komponente Webuploader verwendet. Offiziell unterstützt der Webuploader mehrteiliges Hochladen.

var uploader = WebUploader.create({
   auto: true,
   swf:'/webuploader/Uploader.swf',
   // 文件接收服务端。
   server: '/Uploader.ashx',
   // 内部根据当前运行是创建,可能是input元素,也可能是flash.
   pick: '#filePicker',
   chunked: true,//开启分片上传
   threads: 1,//上传并发数
   //由于Http的无状态特征,在往服务器发送数据过程传递一个进入当前页面是生成的GUID作为标示
   formData: {guid:"<%=Guid.NewGuid().ToString()%>"}
  });

Der mehrteilige Upload von Webuploader besteht darin, die Datei in mehrere Teile aufzuteilen und dann Daten an die von Ihnen definierte Dateiempfangsseite zu senden größer als geteilt Die Größe des Slice wird fragmentiert, und dann werden den Post-Daten zwei Formularelemente hinzugefügt. Ersteres gibt die Reihenfolge des aktuellen Fragments im hochgeladenen Fragment an (beginnend mit 0). Letzteres stellt die Gesamtzahl der Fragmente dar.

Nachdem eine Datei ausgewählt wurde, wurde sie in 7 Shards unterteilt, sodass der Vorgang zum Posten der Daten in Uploader.ashx sieben Mal durchgeführt wurde.

Der jQuery-Webuploader lädt große Dateien in Teilen hoch

Die Formularelemente chunk und chunks in jeder Anfrage und die GUID, um anzuzeigen, dass es sich um Fragmente derselben Datei handelt

Der jQuery-Webuploader lädt große Dateien in Teilen hoch

Nachdem die Daten serverseitig empfangen wurden, können sie gemäß diesen Parametern verarbeitet werden.

1. Erstellen Sie eine temporäre Datei entsprechend der GUID

2. Hängen Sie die empfangenen Fragmentdaten an die Datei an, die der GUID entspricht.

3. Benennen Sie die temporäre Datei entsprechend dem hochgeladenen Dateinamen um

4. Wenn Sie sie direkt ohne Sharding speichern

public void ProcessRequest(HttpContext context)
  {
   context.Response.ContentType = "text/plain";
   //如果进行了分片
   if (context.Request.Form.AllKeys.Any(m => m == "chunk"))
   {
    //取得chunk和chunks
    int chunk =Convert.ToInt32(context.Request.Form["chunk"]);
    int chunks = Convert.ToInt32(context.Request.Form["chunks"]);
 
     
    //根据GUID创建用该GUID命名的临时文件
    string path = context.Server.MapPath("~/1/" + context.Request["guid"]);
    FileStream addFile = new FileStream(path, FileMode.Append, FileAccess.Write);
    BinaryWriter AddWriter = new BinaryWriter(addFile);
    //获得上传的分片数据流
    HttpPostedFile file = context.Request.Files[0];
    Stream stream = file.InputStream;
 
    BinaryReader TempReader = new BinaryReader(stream);
    //将上传的分片追加到临时文件末尾
    AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
    //关闭BinaryReader文件阅读器
    TempReader.Close();
    stream.Close();
    AddWriter.Close();
    addFile.Close();
 
    TempReader.Dispose();
    stream.Dispose();
    AddWriter.Dispose();
    addFile.Dispose();
    //如果是最后一个分片,则重命名临时文件为上传的文件名
    if (chunk == (chunks - 1))
    {
     FileInfo fileinfo = new FileInfo(path);
     fileinfo.MoveTo(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName));
    }
   }
   else//没有分片直接保存
   {
    context.Request.Files[0].SaveAs(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName ));
   }
   context.Response.Write("ok");
  }

gibt es noch einige Probleme Nicht gelöst, obwohl es vorerst den Anforderungen entspricht:

1 Wenn es mehr als 1 gleichzeitigen Upload gibt, beendet ein Split-Upload-Server die Verarbeitung nicht, der zweite Split jedoch Wenn alle gleichzeitig eintreffen, wird die Fehlermeldung angezeigt, dass die Datei belegt ist.
2. Wenn das Sperren das erste Problem löst, wirkt sich das Sperren definitiv auf die Effizienz aus (gleichzeitig kann nur ein Prozess auf den Code zugreifen, der die Datei speichert).
3. Es ist möglich, dass das zweite Fragment zuerst eintrifft und dann das erste Fragment. Dann können Sie den Stream nicht auf einmal anhängen Temporäre Dateien Warten auf alle Nachdem der mehrteilige Upload abgeschlossen ist, wird er in eine Datei gespleißt.

Es ist nur eine Demo. Ich hoffe, jemand kann helfen, die bestehenden Probleme zu lösen.


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn