2009-09-01 22 views
0

嘗試使用Google Gears和ASP.NET上傳文件...我假設您可以接受blob。使用Google Gears和ASP.NET或PHP上傳文件

我在頁面中有FileUpload控件。

<asp:FileUpload runat="server" ID="File1" /> 

然後JavaScript的

var file1 = document.getElementById("<%# File1.ClientID %>"); 
var desktop = google.gears.factory.create('beta.desktop'); 

file1.onclick = function() 
{ 
    desktop.openFiles(openFilesCallback, 
     { 
      singleFile: true, 
      filter: ["image/jpeg"] 
     } 
    ); 
    return false; 
} 

function openFilesCallback(files) 
{ 
    if(files.length == 0) 
    { 
     alert("No files selected"); 
    } 
    else 
    { 
     // 1MB = 1024 * 1024 bytes 
     if(files[0].blob.length > (1024 * 1024)) 
     { 
      alert("File '" + files[0].name + "' is too big to upload"); 
     } 
     else 
     { 
      uploadFile(files[0]); 
     } 
    } 
} 

function uploadFile(file) 
{ 
    var up = google.gears.factory.create("beta.httprequest"); 
    up.open("POST", "upload.ashx"); 
    up.send(file.blob); 
} 

但是,我不知道如何處理它的處理程序。

public void ProcessRequest (HttpContext ctx) 
{ 
    ctx.Response.ContentType = "text/plain"; 
    ctx.Response.Write("Hello World"); 
    ctx.Response.Write(ctx.Request.Files.Count.ToString()); 
    ctx.Response.Write(ctx.Request.Form.Count.ToString()); 
} 

如果我設置一個斷點在任的最後兩個語句,既Files.CountForm.Count返回0。當我沒有我得到在Firebug的異常:Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEMENTED)

如果我不能使用POST通過Gears上傳,可以使用PUT完成嗎?

編輯: PHP代碼將被罰款,以及(因爲我想這樣做,在這兩種語言)

回答

2

我覺得你的問題的根源是,隨着齒輪的實際並未使用多形式/數據上傳機制,而不是實際上在POST請求本身發送文件數據。

所以你需要做的是實際上從輸入處理程序中讀取請求流,並獲取數據。你的代碼應該是這個樣子:

public void ProcessRequest (HttpContext ctx) 
{ 
    var filePath = "SomePath/ToWrite/Filedata.dat"; 
    var stream = ctx.Request.InputStream; 
    var buffer = new byte[stream.Length]; 
    stream.Read(buffer,0,buffer.Lenght); 
    using(var fileStream = new FileStream(filePath,FileMode.Create)) 
    { 
     fileStream.Write(buffer, 0, buffer.Length); 
    } 
} 

當然,你是否寫入文件或數據庫是你的,以及異常處理和搞清楚你是否要創建一個新的文件或追加的現有文件等。另外,由於您的代碼對文件大小有1MB的限制,因此我並不打算限制緩衝區的長度。如果你處理的塊很大,你可能需要選擇一個較小的緩衝區並以大塊的形式從流中讀取,直到數據用完(這可能是因爲你的流的長度大於int.maxvalue,所以可能不太可能)。

如果您需要包含原始文件名稱等內容,您可以選擇多個選項。一種方法是將URL作爲查詢參數發送(確保其編碼正確)。然後你可以從ctx.Request.QueryString [「fileName」]或其他一些文件中讀取它。

另一種選擇是將你需要的數據放到客戶端的一個更復雜的對象上,然後使用JSON序列化所有的數據並把它放到POST中。所以,你的客戶端代碼看起來是這樣的:

function uploadFile(file) 
{ 
    var up = google.gears.factory.create("beta.httprequest"); 
    up.open("POST", "upload.ashx"); 
    var fileInfo = { Name: file.name, Data: file.blob, someOtherData: ...}; 
    up.send(JSON.stringify(fileInfo)); 
} 

您將需要反序列化在服務器端,所以你最有可能從System.Web.Services需要的DataContractJsonSerializer。另一種選擇是James Newton-King的Json.Net庫(http://james.newtonking.com/pages/json-net.aspx)。

internal class FileInfo 
{ 
    public string Name { get; set; } 
    public byte[] Data { get; set; } 
    // .. some other data 
} 


public void ProcessRequest(HttpContext ctx) 
{ 
    var serializer = new DataContractJsonSerializer(typeof(FileInfo)); 
    FileInfo fInfo = (FileInfo)serializer.ReadObject(ctx.Request.InputStream); 
    var path = basePath + fInfo.Name; 
    using(var fileStream = new FileStream(path,FileMode.Create)) 
    { 
     fileStream.Write(fInfo.Data,0,fInfo.Data.Length); 
    } 
} 

恐怕我不禁大爲在PHP端....這是一個很長,很長很長的時間,因爲我已經在PHP土地:)

+0

謝謝,似乎工作(它已經使用多部分形式/數據,所以這不是問題)。雖然不是使用JSON並反序列化數據,但我正在爲其他元數據設置請求標頭。 – SamWM 2010-02-19 10:29:46