Генерация формы на JS (multipart/form-data)

Discussion in 'PHP' started by FindeR, 19 Jul 2011.

  1. FindeR

    FindeR Elder - Старейшина

    Joined:
    15 Nov 2006
    Messages:
    623
    Likes Received:
    138
    Reputations:
    20
    Доброго времени суток.

    Для загрузчика файлов на сервер понадобилось составить вручную post-данные для отправки.

    Работать должно в FF и Хроме\Сафари (т.к. используется drag'n'drop).

    Для FF я составлял строку, исходя из RFC2388, а на сами данные натравил getAsBinary() (а сама отправка - sendAsBinary()).

    При таком раскладе появилась проблема при отправки файлов с русскими названиями - все буквы кириллицы заменяются на буквы r и s. Но т.к. запрос составлялся вручную - не составило труда заменить filename в строке.

    Хром\сафари не понимают getAsBinary() в принципе, т.к. это фишка FF.
    Тут воспользовался formData:
    Code:
    var formData = new FormData(); 
    formData.append("images[]", files[counter_global]); 
    xhr.send(formData);
    
    *xhr - XMLHttpRequest();
    files - массив файлов, такой же, как передаётся в <input type="file" />
    Как в данном варианте возможно сменить в files имя файла? Заменить все символы кириллицы на транслит...
    files[counter_global].fileName доступен на чтение только. Какие ещё варианты могут тут быть? Или, может, сам подход неправильный?

    upd: по сути, имеем переменную file, в которой лежит, собственно, ссылка на файл из <input type="file" />
    Требуется переписать эту переменную, изменив лишь имя файла.
     
    #1 FindeR, 19 Jul 2011
    Last edited: 19 Jul 2011
  2. |qbz|

    |qbz| Banned

    Joined:
    25 Dec 2009
    Messages:
    385
    Likes Received:
    169
    Reputations:
    65
    Никак. Иначе это была бы мощная дыра в браузере. Помню давно было такое в Опере, но уже давно исправили.
     
  3. FindeR

    FindeR Elder - Старейшина

    Joined:
    15 Nov 2006
    Messages:
    623
    Likes Received:
    138
    Reputations:
    20
    Может, я немного неверно выразился, но переписать нужно именно часть files.name (files.fileName) уже полученных через input переменных. Эмуляция отправки формы, но с другим именем в заголовке. Файл в данном случае не меняется.


    *
    При отправке файла POST-ом в заголовок пишется подобная фигня:
    Code:
    Content-Disposition: form-data; name="images[]"; filename="1a.jpg"
    
    Content-Type: application/octet-stream
    
    А дальше сам файл.
    Вот filename и требуется сменить.
     
    #3 FindeR, 19 Jul 2011
    Last edited: 19 Jul 2011
  4. |qbz|

    |qbz| Banned

    Joined:
    25 Dec 2009
    Messages:
    385
    Likes Received:
    169
    Reputations:
    65
    Я читал только каждое 10-ое слово в теме, не много не сосредоточен, но чую, что тебе надо составить заголовок для отправки мультипарта... Это как-бы составляется с помощью боундариес, если я не ошибаюсь... Ща примерчик скину...
    Code:
    POST /files?X-Progress-Id=1057856061 HTTP/1.1
    Host: xxx.net
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    Referer: http://xxx.net/
    Cookie: _xxx_session=BAh7ByIQX2NxxxZfdG9rZW4iMStpM1NBQWpiNE5PYmF3MDBSTkVoVDEvaWxyN21HbVFIU3Y1dTBmaWl6d009Ig9zZXNzaW9uX2lkIiVhOTI1ZWRhMzYzYzlhNjU3YzcyNTQxZTkyOTkwZmQ0ZA%3D%3D--75dc590e87b25fae2a33a2a14eab3972ecb56f14
    [B]Content-Type: multipart/form-data; [/B]boundary=---------------------------82342068632582
    Content-Length: 2594
    -----------------------------82342068632582
    Content-Disposition: form-data; name="utf8"
    
    ✓
    -----------------------------82342068632582
    Content-Disposition: form-data; name="authenticity_token"
    
    +i3SAAjb4NObaw00RNEhT1/ilr7mGmQHSv5u0fiizwM=
    -----------------------------82342068632582
    Content-Disposition: form-data; name="file"; filename="[B]WebMoneyCA.crt[/B]"
    Content-Type: application/x-x509-ca-cert
    
    -----BEGIN CERTIFICATE-----
    MIIFsTCCA5mgAwIBAgIQA7dHzSZ7uJdBxFycIWn+WjANBgkqhkiG9w0BAQUFADBr
    MSswKQYDVQQLEyJXTSBUcmFuc2ZlciBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzMRgw
    FgYDVQQKEw9XTSBUcmFuc2ZlciBMdGQxIjAgBgNVBAMTGVdlYk1vbmV5IFRyYW5z
    ZmVyIFJvb3QgQ0EwHhcNMTAwMzEwMTczNDU2WhcNMzUwMzEwMTc0NDUxWjBrMSsw
    KQYDVQQLEyJXTSBUcmFuc2ZlciBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzMRgwFgYD
    VQQKEw9XTSBUcmFuc2ZlciBMdGQxIjAgBgNVBAMTGVdlYk1vbmV5IFRyYW5zZmVy
    IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDFLJXtzEkZ
    xLj1HIj9EhGvajFJ7RCHzF+MK2ZrAgxmmOafiFP6QD/aVjIexBqRb8SVy38xH+wt
    hqkZgLMOGn8uDNpFieEMoX3ZRfqtCcD76KDySTOX1QUwHAzBfGuhe2ZQULUIjxdP
    Ra4NDyvmXh4pE/s1+/7dGbUZs/JpYYaD2xxAt5PDTjylsKOk4FMb5kv6jzORkXku
    5UKFGUXEXbbf1xzgYHMIzoeJGn+iPgVFYAvkkQyvxEaVj0lNE+q/ua761krgCo47
    BiH1zMFzkv4uNHEZfe/lyHaozzbsu6yaK3EdrURSLuWrlxKy9yo3xDe9TPkzkhPe
    JPbV7YgvUUtWSeAJpksBU8GCALEhSgX0fHckuJFj9QB3YecHBvjdSiAUuntwM/iH
    vtSOXEUHxqW75E2Gq/2L4vBcxArXVdbUrVQDF3klzYu17OFgfe1hHHMHzgr4HBML
    ZiRCcvNLqghBCVxu1DM15YDfw+wnNV/5dUPx60tiocmCZpJKTwVl8gc85QCPyREu
    jey8F0kgdgssQosPXXXWDg7X4Ifw20VkplHZDr29K5HdwLe56TvOI/4H24XJdqpA
    xoLBx9PL6ZXxH52wU0bSluL8/joXGzavFrhsXH7jJocH6tsFVzBZrmnVswbUMHDN
    L3xSnr5fAAXXZa7UwHd3pq/fsdG7s9PByQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw
    DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUsTCnSwOZT4Q2HBN9V/TrafuIG8Mw
    EAYJKwYBBAGCNxUBBAMCAQAwXXXXKoZIhvcNAQEFBQADggIBAAy5jHDFpVWtF209
    N30I+LHsiqMaLUmYDeV6sUBJqmWAZav7pWnigiMLuJd9yRa/ow6yKlKPRi3sbKaB
    wsAQ+xnz811nLFBBdS4PkwlHu1B7P4B2YbcqmF6k1QieJBZxOn7wledtnoBAkZ4d
    6HEW1OM5cvCoyj8YAdJTZIBzn61aNt/viPvypIUQf6Ps6Q2daNEAj7DoxIY8crnO
    aSIGdGmlT/y/edSqWv9Am5e9KXkJhQWMnGXh43wJYyHTetxVWPS43bW7gIUADYyc
    KSH3isrBN5xQOFXMfL+lVHHSs7ap23DOo7xIDenm5PWz+QdDDFz3zLVeRovnkIdk
    a/Wgk3f6rFfKB0y5POJ+BJvkorIYNZiN3dnmc6cDP840BUMv3BUrOe8iSy5lRr8m
    R+daktbZfO8E/rAb3zEdN+KG/CNJfAnQvp6DT4LqY/J9pG+VusH5GpUwuXr7UqLw
    End1LRp7qm28Cic7fegUnnUpkuF4ZFq8pWq8w59sOWlRuKBuWX46OghMrjgD0AN1
    hlA2/d5ULImX70Q2te3xiS1vrQhu77mkb/jA4/9+YfeT7VMpbnC3OoHiZ2bjudKn
    thlOs+AuUvzB4Tqo62VSF5+r0sYI593S+STmaZBAzsoaoEB7qxqKbEKCvXb9BlXk
    L76xIOEkbSIdPIkGXM4aMo4mTVz7
    -----END CERTIFICATE-----
    
    -----------------------------82342068632582
    Content-Disposition: form-data; name="commit"
    
    Upload
    -----------------------------82342068632582--
    
    HTTP/1.x 200 OK
    Server: nginx
    Date: Tue, 19 Jul 2011 18:12:16 GMT
    Content-Type: text/html; charset=utf-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Keep-Alive: timeout=3
    Status: 200 OK
    Etag: "c1fdc6f35c0c97f1bdd76afff9b2969f"
    X-UA-Compatible: IE=Edge,chrome=1
    Set-Cookie: _xxx_session=BAh7XXXQX2NxxxZfdG9rZW4iMStpM1NBQWpiNE5PYmF3MDBSTkVoVDEvaWxyN21HbVFIU3Y1dTBmaWl6d009Ig9zZXNzaW9uX2lkIiVhOTI1ZWRhMzYzYzlhNjU3YzcyNTQxZTkyOTkwZmQ0ZCIRdXBsb2FkZWRfaWRzWwZpAwGq5g%3D%3D--a6f806b628a3d4eebd08c50d4765bb704b27ea52; domain=.xxx.net; path=/; HttpOnly
    Cache-Control: max-age=0, private, must-revalidate
    Content-Encoding: gzip
     
  5. FindeR

    FindeR Elder - Старейшина

    Joined:
    15 Nov 2006
    Messages:
    623
    Likes Received:
    138
    Reputations:
    20
    Заголовок и сам запрос я могу составить.

    Проблема в том, как отправить бинарные данные в браузерах, отличных от FF ?

    В FF можно, во-первых, получить все файлы в бинарном виде (методом getAsBinary()), запихнуть полученное к заголовкам, а потом отправить методом sendAsBinary().
    Но, повторюсь, эти методы есть только в лисе. Мне нужна ещё, как минимум, поддержка Хрома и Сафари.
     
  6. FindeR

    FindeR Elder - Старейшина

    Joined:
    15 Nov 2006
    Messages:
    623
    Likes Received:
    138
    Reputations:
    20
    Отвечу сам на свой же вопрос.
    У новых браузеров появилась читалка файлов - FileReader.
    Т.е. reader = new FileReader();
    Потом на reader.onload вешаем нужную функцию и загружаем читалкой файл в бинарном виде - reader.readAsBinaryString(file);


    Но теперь новая проблема. Абсолютно одинаково отправляю файл лисой и хромом. В лисе файл приходит нормально, а в хром через каждые N байт в файле втыкает какой-то мусор. Вес файла вырастает процентов на 20. На хабре нашёл подобную проблему, но там она решена не была. Может, кто-то сталкивался с подобной ХРОМой фигнёй?

    Попробовал заливать текстовый документ - он не меняется.
    С картинками проблемы.

    По ссылке ниже архив с двумя картинками - одна нормальная, вторая залита через хром и "сломалась".
    http://narod.yandex.ru/disk/19532860001/images.zip
     
  7. |qbz|

    |qbz| Banned

    Joined:
    25 Dec 2009
    Messages:
    385
    Likes Received:
    169
    Reputations:
    65
    Попробуй не на картинке тестить, а на текстовом файле, чтобы потом можно было легче отличить где мусор а где нет.
     
  8. FindeR

    FindeR Elder - Старейшина

    Joined:
    15 Nov 2006
    Messages:
    623
    Likes Received:
    138
    Reputations:
    20
    Я же написал в том сообщении "Попробовал заливать текстовый документ - он не меняется."

    В общем, в итоге сделал проще - отдельной переменной передаю имя файла модифицированное, как и требовалось...

    А с Хромом действительно имеем место быть проблема при передаче файла в бинарном виде.