Загружайте файлы с помощью Google Gears и ASP.NET или PHP - PullRequest
0 голосов
/ 01 сентября 2009

Попытка загрузки файлов с помощью Google Gears и ASP.NET ... Я предполагаю, что вы можете, так как HttpRequest API принимает большие двоичные объекты.

У меня есть элемент управления 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.Count вернут 0. Когда я не получу, я получу исключение в Firebug: Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEMENTED)

Если я не могу использовать POST для загрузки через Gears, можно ли это сделать с помощью PUT?

Edit: PHP-код тоже подойдет (так как я хочу сделать это на обоих языках)

1 Ответ

2 голосов
/ 17 февраля 2010

Я думаю, что корень вашей проблемы в том, что с шестерёнками вы фактически не используете механизм multipart-form / data upload, а фактически отправляете данные вашего файла в самом запросе 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);
    }
}

Конечно, решать, будете ли вы записывать в файл или базу данных, а также обрабатывать исключения и выяснять, хотите ли вы создать новый файл или добавить существующий файл и т. Д. Кроме того, поскольку ваш код имел Ограничение размера файла 1 МБ, я не стал ограничивать длину буфера. Если вы потенциально имеете дело с очень большими блоками, вам может понадобиться выбрать меньший буфер и читать из потока порциями до тех пор, пока у вас не закончатся данные (это будет в случае, когда длина вашего потока была> 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));
}

Вам потребуется десериализовать его на стороне сервера, поэтому вам, скорее всего, понадобится DataContractJsonSerializer из System.Web.Services. Другой вариант - библиотека 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:)

...