Снимки, загруженные с помощью valums ajax upload и OctetStreamReader, не работают в IE - Java / JSP - PullRequest
1 голос
/ 17 октября 2011

У меня проблема с загрузкой изображений в Internet Explorer 7, 8 и 9 (другие версии не тестировались). Он хорошо работает в FF и Chrome, но по какой-то причине картинка загружается неправильно, когда я пытаюсь загрузить ее в любой версии IE.

Под этим я подразумеваю, что файл загружается в правильный каталог с правильным именем, но я не могу открыть его в любых программах для редактирования изображений.

Кроме того, когда я открываю picutre в Notepad ++, я вижу, что на изображении отображаются метаданные, например:

----------------------------- 7db1f6c907fe Content-Disposition: форма-данные; Name = "qqfile"; имя файла = "jingjang.jpg" Тип содержимого: изображение / JPEG

(хеш-код здесь)

----------------------------- 7db1f6c907fe -

Если я удалю код, картинка будет работать нормально! Так может кто-нибудь сказать мне, что генерирует код и как мне его остановить? :)

Я использую Valums Ajax Upload на моей странице JSP:

var imageFolder = "images/upload/<%=user.getUsername()%>/temp/";
new qq.FileUploader({

element: document.getElementById('TempUploadButton'),
action: 'OctetStreamReader',
debug: false,
multiple: false,
params: {"type" : "user"},

onComplete: function(id, fileName) {    
    var d = new Date();
    $("#UserPageAvatarPic a img").attr("src", imageFolder+"<%=user.getUsername()%>.jpg?cache="+d.getTime() );
},
onSubmit : function(id, fileName) {
    // hide all prev elements
    $('#TempUploadButton ul.qq-upload-list li').each(function() {
        $(this).hide();
    });
}

});

И OctetStreamReader как мой сервлет

    public class OctetStreamReader extends HttpServlet {

private static final long serialVersionUID = 6748857432950840322L;
private static final String DESTINATION_DIR_PATH = "files";
private static String realPath;
UserService userService = UserService.getService();

/**
 * {@inheritDoc}
 * @param config
 * @throws ServletException
 */
@Override
public void init(ServletConfig config) throws ServletException {
    super.init(config);
    realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH) + "/";
}

/** 
 * Handles the HTTP <code>POST</code> method.
 * @param request servlet request
 * @param response servlet response
 * @throws ServletException if a servlet-specific error occurs
 * @throws IOException if an I/O error occurs
 */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException {
    User user = userService.getUser(((Integer) request.getSession().getAttribute("user")).intValue());
    String type = request.getParameter("type");
    String username = user.getUsername();
    PrintWriter writer = null;
    InputStream is = null;
    FileOutputStream fos = null;
    type = "user";
    try {
        writer = response.getWriter();
    } catch (IOException ex) {
        log(OctetStreamReader.class.getName() + "has thrown an exception: " + ex.getMessage());
    }

    try {
        String filename = "";
        if (type.equals("user")) {
            realPath = getServletContext().getRealPath("/images/upload/" + username + "/temp/");
            is = request.getInputStream();
            String strDirectoy = getServletContext().getRealPath("/images/upload/" + username + "/temp/" );
            boolean success = (new File(strDirectoy)).mkdir();
            File f1 = new File(strDirectoy);
            File[] children = f1.listFiles();
            filename = username + ".jpg";
        }
        if (type.equals("post"))  {
            realPath = getServletContext().getRealPath("/images/upload/" + username + "/post/");
            is = request.getInputStream();
            String strDirectoy = getServletContext().getRealPath("/images/upload/" + username + "/post/" );
            boolean success = (new File(strDirectoy)).mkdir();
            File f1 = new File(strDirectoy);
            File[] children = f1.listFiles();
            filename = Calendar.getInstance().getTimeInMillis()+".jpg";
        }
        if (type.equals("editpost"))  {
            realPath = getServletContext().getRealPath("/images/upload/" + username + "/editpost/");
            is = request.getInputStream();
            String strDirectoy = getServletContext().getRealPath("/images/upload/" + username + "/editpost/" );
            boolean success = (new File(strDirectoy)).mkdir();
            File f1 = new File(strDirectoy);
            File[] children = f1.listFiles();
            filename = Calendar.getInstance().getTimeInMillis() + ".jpg";
        }


        fos = new FileOutputStream(new File(realPath + "/" + filename), false);
        IOUtils.copy(is, fos);
        response.setStatus(response.SC_OK);
        writer.print("{success: true, filename: \"" + filename + "\"}");
    } catch (FileNotFoundException ex) {
        response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
        writer.print("{success: false}");
        log(OctetStreamReader.class.getName() + "has thrown an exception: " + ex.getMessage());
    } catch (IOException ex) {
        response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
        writer.print("{success: false}");
        log(OctetStreamReader.class.getName() + "has thrown an exception: " + ex.getMessage());
    } finally {
        try {
            fos.close();
            is.close();
        } catch (IOException ignored) {
        }
    }
 writer.flush();
    writer.close();
}
}

Также в fileuploader.js я пытался изменить тип контента с application / octet-stream на multipart / form-data

        /**
 * Sends the file identified by id and additional query params to the server
 * @param {Object} params name-value string pairs
 */    
_upload: function(id, params){
    var file = this._files[id],
        name = this.getName(id),
        size = this.getSize(id);

    this._loaded[id] = 0;

    var xhr = this._xhrs[id] = new XMLHttpRequest();
    var self = this;

    xhr.upload.onprogress = function(e){
        if (e.lengthComputable){
            self._loaded[id] = e.loaded;
            self._options.onProgress(id, name, e.loaded, e.total);
        }
    };

    xhr.onreadystatechange = function(){            
        if (xhr.readyState == 4){
            self._onComplete(id, xhr);                    
        }
    };

    // build query string
    params = params || {};
    params['qqfile'] = name;
    var queryString = qq.obj2url(params, this._options.action);

    xhr.open("POST", queryString, true);
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
    xhr.setRequestHeader("Content-Type", "multipart/form-data");
    xhr.send(file);
},

Ответы [ 2 ]

1 голос
/ 08 мая 2012

Используйте это:

InputStream is = null;
         // Check that we have a file upload request
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        // Create a factory for disk-based file items
        if (isMultipart) {
            FileItemFactory factory = new DiskFileItemFactory();
            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            try {
                // Parse the request
                ArrayList<DiskFileItem> files = (ArrayList<DiskFileItem>) upload.parseRequest(request);
                if (!files.isEmpty()) {
                    is = files.get(0).getInputStream();
                }
            } catch (FileUploadException ex) {
                Logger.getLogger(OctetStreamReader.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            is = request.getInputStream();
        }
1 голос
/ 17 октября 2011

При загрузке файлов HTML по умолчанию используется multipart/form-data кодировка запроса (это позволяет загружать несколько файлов и / или смешивать обычные значения полей ввода в one запрос).Однако вы не анализируете и не извлекаете отдельные части данных формы из тела запроса, вместо этого вы читаете и записываете полное тело запроса в неизмененном виде в файл.

is = request.getInputStream();
fos = new FileOutputStream(new File(realPath + "/" + filename), false);
IOUtils.copy(is, fos);

Это действительно никогда не сработает.То, что вы сказали, что это работает в FF / Chrome, мне не под силу.Возможно, вы неправильно интерпретируете результаты или вообще не тестировали его в этих браузерах с двоичными файлами.

Вам необходимо использовать Apache Commons FileUpload , чтобы извлечь детали из multipart/form-dataзапрос.Или, когда вы уже используете Servlet 3.0, вы также можете использовать API Servlet, предоставленный методом HttpServletRequest#getParts().

См. Также:


Не связано к конкретной проблеме, у вас есть еще одна проблема с кодом, опубликованным до сих пор.Вы храните загруженные файлы в веб-содержимом расширенной WAR.Это далеко от надежного места постоянного хранения.Каждый раз, когда вы повторно развертываете новую WAR, все эти файлы будут потеряны.Вам нужно будет делать их резервные копии каждый раз, что просто неуклюже и подвержено ошибкам.Скорее храните их в фиксированном месте за пределами расширенной папки WAR.

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...