2012-10-24 67 views
1

我有这个问题。 在合成中,我有一个下载按钮,单击时,执行这样一个Ajax请求:使用Ajax请求下载文件Extjs4

Ext.Ajax.request({ 
url: 'DownloadServlet', 
method: 'GET',  
}); 

该请求由一个servlet读取默认的文件进行处理。 该文件的读取是成功的,事实上,在萤火虫中,GET的状态是“200”。

问题是前端(extjs)似乎无法管理下载文件。我期望浏览器显示经典的更多窗口来下载文件。

什么可能呢?谢谢

回答

1

您无法使用AJAX调用下载文件。基本上有两种解决方案:坚固而简单。

简单:只需使用window.popup或document.location.href来重定向您的文件存储的URL,您将获得正常的浏览器下载方法。硬件:你可以通过AJAX调用获得二进制或base64编码的文件内容,并创建一个带有base64编码href的下载链接。在Chrome中,它将如下所示:

<a href="base64,mime-type,...encoded trash..." download="download"> 

对于其他浏览器有一些解决方案,但目前它仅适用于Chrome。对于其他浏览器,我使用的代码那样:

var showSave; 

// Feature test: Does this browser support the download attribute on anchor tags? (currently only Chrome) 
var DownloadAttributeSupport = 'download' in document.createElement('a'); 

// Use any available BlobBuilder/URL implementation: 
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; 
var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; 

// IE 10 has a handy navigator.msSaveBlob method. Maybe other browsers will emulate that interface? 
// See: http://msdn.microsoft.com/en-us/library/windows/apps/hh441122.aspx 
navigator.saveBlob = navigator.saveBlob || navigator.msSaveBlob || navigator.mozSaveBlob || navigator.webkitSaveBlob; 

// Anyway, HMTL5 defines a very similar but more powerful window.saveAs function: 
// http://www.w3.org/TR/file-writer-api/#the-filesaver-interface 
window.saveAs = window.saveAs || window.webkitSaveAs || window.mozSaveAs || window.msSaveAs; 
// However, this is not supported by any browser yet. But there is a compatibility library that 
// adds this function to browsers that support Blobs (except Internet Exlorer): 
// http://eligrey.com/blog/post/saving-generated-files-on-the-client-side 
// https://github.com/eligrey/FileSaver.js 

// mime types that (potentially) don't trigger a download when opened in a browser: 
var BrowserSupportedMimeTypes = { 
    "image/jpeg": true, 
    "image/png": true, 
    "image/gif": true, 
    "image/svg+xml": true, 
    "image/bmp": true, 
    "image/x-windows-bmp": true, 
    "image/webp": true, 
    "audio/wav": true, 
    "audio/mpeg": true, 
    "audio/webm": true, 
    "audio/ogg": true, 
    "video/mpeg": true, 
    "video/webm": true, 
    "video/ogg": true, 
    "text/plain": true, 
    "text/html": true, 
    "text/xml": true, 
    "application/xhtml+xml": true, 
    "application/json": true 
}; 

// Blobs and saveAs (or saveBlob) : 
if (BlobBuilder && (window.saveAs || navigator.saveBlob)) { 
    // Currently only IE 10 supports this, but I hope other browsers will also implement the saveAs/saveBlob method eventually. 
    showSave = function (data, name, mimeType) { 
     var builder = new BlobBuilder(); 
     builder.append(data); 
     var blob = builder.getBlob(mimetype||"application/octet-stream"); 
     if (!name) name = "Download.bin"; 
     // I don't assign saveAs to navigator.saveBlob (or the other way around) 
     // because I cannot know at this point whether future implementations 
     // require these methods to be called with 'this' assigned to window (or 
     // naviagator) in order to work. E.g. console.log won't work when not called 
     // with this === console. 
     if (window.saveAs) { 
      window.saveAs(blob, name); 
     } 
     else { 
      navigator.saveBlob(blob, name); 
     } 
    }; 
} 
else if (window.Blob && URL && window.atob) { 
    // atob to base64_decode the data-URI 
    showSave = function (data, name, mimetype) { 
     var image_data = atob(data); 
     // Use typed arrays to convert the binary data to a Blob 
     var arraybuffer = new ArrayBuffer(image_data.length); 
     var view = new Uint8Array(arraybuffer); 
     for (var i=0; i<image_data.length; i++) { 
      view[i] = image_data.charCodeAt(i) & 0xff; 
     } 
     var blob = new Blob([arraybuffer], {type: 'application/octet-stream'}); 

     // Use the URL object to create a temporary URL 
     var url = URL.createObjectURL(blob); 
     //window.open(url, '_blank', ''); 
     document.location.href = url 
    } 
} 
// Blobs and object URLs: 
else if (BlobBuilder && URL) { 
    // Currently WebKit and Gecko support BlobBuilder and object URLs. 
    showSave = function (data, name, mimetype) { 
     var blob, url, builder = new BlobBuilder(); 
     builder.append(data); 
     if (!mimetype) mimetype = "application/octet-stream"; 
     if (DownloadAttributeSupport) { 
      blob = builder.getBlob(mimetype); 
      url = URL.createObjectURL(blob); 
      // Currently only Chrome (since 14-dot-something) supports the download attribute for anchor elements. 
      var link = document.createElement("a"); 
      link.setAttribute("href",url); 
      link.setAttribute("download",name||"Download.bin"); 
      // Now I need to simulate a click on the link. 
      // IE 10 has the better msSaveBlob method and older IE versions do not support the BlobBuilder interface 
      // and object URLs, so we don't need the MS way to build an event object here. 
      var event = document.createEvent('MouseEvents'); 
      event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null); 
      link.dispatchEvent(event); 
     } 
     else { 
      // In other browsers I open a new window with the object URL. 
      // In order to trigger a download I have to use the generic binary data mime type 
      // "application/octet-stream" for mime types that browsers would display otherwise. 
      // Of course the browser won't show a nice file name here. 
      if (BrowserSupportedMimeTypes[mimetype.split(";")[0]] === true) { 
       mimetype = "application/octet-stream"; 
      } 

      blob = builder.getBlob(mimetype); 
      url = URL.createObjectURL(blob); 
      //window.open(url, '_blank', ''); 
      document.location.href = url 
     } 
     // The timeout is probably not necessary, but just in case that some browser handle the click/window.open 
     // asynchronously I don't revoke the object URL immediately. 
     setTimeout(function() { 
      URL.revokeObjectURL(url); 
     }, 250); 

     // Using the filesystem API (http://www.w3.org/TR/file-system-api/) you could do something very similar. 
     // However, I think this is only supported by Chrome right now and it is much more complicated than this 
     // solution. And chrome supports the download attribute anyway. 
    }; 
} 
// data:-URLs: 
else if (!/\bMSIE\b/.test(navigator.userAgent)) { 
    // IE does not support URLs longer than 2048 characters (actually bytes), so it is useless for data:-URLs. 
    // Also it seems not to support window.open in combination with data:-URLs at all. 
    showSave = function (data, name, mimetype) { 
     if (!mimetype) mimetype = "application/octet-stream"; 
     // Again I need to filter the mime type so a download is forced. 
     if (BrowserSupportedMimeTypes[mimetype.split(";")[0]] === true) { 
      mimetype = "application/octet-stream"; 
     } 
     // Note that encodeURIComponent produces UTF-8 encoded text. The mime type should contain 
     // the charset=UTF-8 parameter. In case you don't want the data to be encoded as UTF-8 
     // you could use escape(data) instead. 
     window.open("data:"+mimetype+";base64,"+data, '_blank', ''); 
    }; 
} 
// Internet Explorer before version 10 does not support any of the methods above. 
// If it is text data you could show it in an textarea and tell the user to copy it into a text file. 

更新时间: 如果你确定使用闪光灯,这里是对于非Chrome浏览器,备用解决方案: https://github.com/dcneiner/Downloadify

3

试试这个

downloadWhatever : function() { 
    Ext.core.DomHelper.append(document.body, { 
      tag : 'iframe', 
      id : 'downloadIframe', 
      frameBorder : 0, 
      width : 0, 
      height : 0, 
      css : 'display:none;visibility:hidden;height:0px;', 
      src : '/your/restful/url/' 
     }); 
    }, 

服务器端弹簧(如果你不知道)

@RequestMapping(value = "/url", method = RequestMethod.GET) 
public void download(HttpServletRequest request, 
     HttpServletResponse response) throws ServletRequestBindingException, IOException { 
    String tempFile = .. get your file 
    File file = new File(tempFile); 
      // in case you have zipped it ... 
      // else set the correct ContentType 
    response.setContentType("application/zip"); 
    response.setContentLength((int) file.length()); 
    response.setHeader("fileName", file.getName()); 
    response.setHeader("Content-Disposition", "attachment; filename="+ file.getName()); 

    InputStream in = new FileInputStream(file); 
    OutputStream out = response.getOutputStream(); 
    byte[] buffer = new byte[1024]; 
    int read = 0; 
    while ((read = in.read(buffer, 0, buffer.length)) != -1) { 
     out.write(buffer, 0, read); 
    } 

    in.close(); 
    out.flush(); 
    out.close(); 
}