【问题标题】:Pictures uploaded with valums ajax upload and OctetStreamReader dosn't work in IE - Java/JSP使用 valuems ajax 上传和 OctetStreamReader 上传的图片在 IE 中不起作用 - Java/JSP
【发布时间】:2011-12-09 10:18:20
【问题描述】:

我在 Internet Explorer 7、8 和 9 中上传图片时遇到问题(尚未测试其他版本)。它在 FF 和 Chrome 中运行良好,但由于某种原因,当我尝试在任何版本的 IE 中上传时,图片上传错误。

我的意思是文件以正确的名称上传到正确的目录中,但我无法在任何图片编辑程序中打开它。

此外,当我在 Notepad++ 中打开图片时,我看到图片中有一些元数据显示如下:

------------------7db1f6c907fe 内容处置:表单数据;名称="qq文件";文件名="jingjang.jpg" 内容类型:image/jpeg

(此处为哈希码)

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

如果我删除代码图片可以正常工作!那么谁能告诉我是什么生成了代码以及如何停止它? :)

我在我的 JSP 页面上使用 Valums Ajax Upload:

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 作为我的 servlet

    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);
},

【问题讨论】:

    标签: java ajax servlets file-upload


    【解决方案1】:

    HTML 文件上传默认使用the multipart/form-data request encoding(这是为了能够上传多个文件和/或在一个请求中混合正常输入字段值)。但是,您不是从请求正文中解析和提取单个表单数据部分,而是读取和写入未修改的 整个 请求正文到文件中。

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

    这确实是行不通的。你说它适用于 FF/Chrome 超出了我的范围。也许您对结果有误解,或者根本没有在那些带有二进制文件的浏览器中对其进行测试。

    您需要使用Apache Commons FileUploadmultipart/form-data 请求中提取部分。或者,当您已经使用 Servlet 3.0 时,您还可以使用 Servlet API 提供的HttpServletRequest#getParts() 方法。

    另见:


    与具体问题无关,到目前为止发布的代码还有另一个问题。您将上传的文件存储在扩展 WAR 的 Web 内容中。这远非一个可靠的永久存储位置。每次重新部署新的 WAR 时,所有这些文件都会丢失。您每次都需要备份它们,这很笨拙且容易出错。而是将它们存储在扩展的 WAR 文件夹之外的固定位置。

    另见:

    【讨论】:

    • 感谢您的回答。我不太明白你的意思,为什么我这样做的方式不应该起作用。我从 valums 主页获得了 OctetStreamReader.java 以及整个包,并且只对其进行了一点修改:link 我还尝试使用 Apache Commons FileUpload,当我使用以下表单提交图片时它工作正常: 但它不适用于 Ajax Uploader,我需要在提交整个表单之前上传动态图片。这就是为什么我试图回到这个
    【解决方案2】:

    使用这个:

    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();
            }
    

    【讨论】:

      猜你喜欢
      • 2012-07-22
      • 2013-04-02
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2012-10-20
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多