0

尝试使用 Google Gears 和 ASP.NET 上传文件...我假设您可以,因为HttpRequest API接受 blob。

我在页面中有 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.Count返回Form.Count0。当我没有设置断点时,Firebug 中会出现异常:Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEMENTED)

如果我不能使用 POST 通过 Gears 上传,可以使用 PUT 完成吗?

编辑: PHP代码也可以(因为我想用两种语言来做)

4

1 回答 1

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 ( http://james.newtonking.com/pages/json-net.aspx ) 的 Json.Net 库。

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 领域以来已经很久很久了 :)

于 2010-02-17T02:32:00.880 回答