React使用Post方式从服务器下载文件

1.问题背景:

       之前下载,我都是使用get方式,也就是window.open打开新的标签页的方式,当传递给服务器的下载参数过多的时候,地址栏就会变得特别丑陋。

 想在React中使用POST方式下载文件,无奈在网上搜到的React相关的资料过少,把自己经过探索后成功实践的案例与你分享。

2.解决方案:

      在React中使用ReactDOM创建临时form表单,自动提交。

3. 解决步骤:

   相信大家都是从网上搜到的JQuery代码写的传统处理方式,如下:

var questiontype = $('#QuestionType').combobox('getValue');//得到题型名称
    var form = $("<form>");   //定义一个form表单
    form.attr('style','display:none');   //在form表单中添加查询参数
    form.attr('method','post');//设置或返回将数据发送到服务器的HTTP方法
    form.attr('action', "GetExcel");
      
    var input1 = $('<input>'); 
    input1.attr('type','hidden'); 
    input1.attr('name','exportPostTime'); 
    input1.attr('value',questiontype); 
      
    $('body').append(form);  //将表单放置在web中
    form.append(input1);   //将查询参数控件提交到表单上
    form.submit();   //表单提交


 那么为了使用React,该如何改造这段代码呢?划重点的来了

 

3.1)方案一、首先在react组件的render函数里面建立一个隐藏的div ,例如:

<div id='downloadDiv' style={{display:'none'}}></div>

3.2 )  方案一、 用户在页面上触发下载按钮后,执行以下函数:在隐藏的div里面创建临时表单,获取表单,提交表单,在div节点卸载临时表单。

downloadDetailData=()=>{

var divElement= document.getElementById("downloadDiv");
var downloadUrl=`${apiBasePath}/api/xxxxx/downloadDetailData`;
var params=JSON.stringify({
     key:'value'
})
ReactDOM.render(
      <form action={downloadUrl} method="post">
        <input name="params" type="text" value={params}/> 
      </form>,
      divElement
  )
ReactDOM.findDOMNode(divElement).querySelector('form').submit();
ReactDOM.unmountComponentAtNode(divElement);

}

 

3.3)方案二,以用于解决浏览器兼容问题

       评论区有小伙伴(hzw29106)报告,说chrome和IE没有问题,360浏览器切换页面时会导致自动下载的问题,经过小伙伴实践已找到方法,已经在项目用到并已上线,暂没发现有浏览器兼容问题 。以下是另一种方法实现:

let formElement = document.createElement('form'); 
formElement.style.display = "display:none;"; 
formElement.method = 'post'; 
formElement.action = ${apiBasePath}/api/xxxxx/downloadDetailData; 
formElement.target = 'callBackTarget'; 
let inputElement = document.createElement('input'); 
inputElement.type = 'hidden'; 
inputElement.name = "params" ; 
inputElement.value = params; 
formElement.appendChild(inputElement); 
document.body.appendChild(formElement); 
formElement.submit(); 
document.body.removeChild(formElement);

    大家在使用方案二的时候,如果遇到问题,可以私信博友hzw29106或者私信博主我,感谢小伙伴无私的分享。

 

 

 

3.4)从服务器接收参数,并write文件流

怎么在服务器接收params参数,我就无需多言了吧,比如你用的是SpringMVC,那么  @RequestMapping(value = "/downloadDetailData", method = RequestMethod.POST)

参数 为(@RequestParam(value="params")String params, HttpServletRequest request, HttpServletResponse response) 就可以了。

将params转化为指定的对象类型,用google 的GSON工具类就可以了

Gson gson = new Gson();
MyBean bean = gson.fromJson(params, MyBean .class);

好了,打完收工,希望对你有益 。

 

欢迎关注我的微信公众号-搜索 “前端琅琊阁“ 即可

或者向我提问:

向我提问

 

 

已标记关键词 清除标记
<div class="post-text" itemprop="text"> <p>I need to download a file from the server when a button is clicked.</p> <p>I created a MaterialUI button and on its onclick callback i call an action of the container component <strong>connected</strong>. </p> <p>The action is asynchronous and does an ajax POST:</p> <pre><code>export const onXlsxClick = () => dispatch => { const urlParams = { filters: { aggregation: 'macro_area', chart_resolution: '1_hour', chart_from: '1478080363', chart_to: '1477993963' }, labels: ['PROVA1', 'PROVA2'], series: [ { label: null, timestamp: 1478080363, values: [123, 345] }, { label: null, timestamp: 1477993963, values: [153, 3435] } ] }; return $.ajax({ url:'/rest/export/chart/xlsx', type: 'POST', dataType: 'application/json', contentType: 'application/json', data: JSON.stringify(urlParams) }) .done(data => { console.log('success'); }) .fail(error => { console.log(error); }); }; </code></pre> <p>The server receive the request and handle it correctly through this REST service:</p> <pre><code>@POST @Path("xlsx") @Produces("application/vnd.ms-excel") public Response getXlsx(ChartExportRequest request) { ResponseBuilder responseBuilder; ChartExportRequestDTO reqDto = null; try { reqDto = parseDTO(request); checkRequestDTO(reqDto); ExportDTO dto = getXlsxProvider().create(reqDto); responseBuilder = Response.ok(dto.getFile()) .header("Content-disposition", "attachment;filename=" + dto.getFileName()); } catch(Exception e) { logger.error("Error providing export xlsx for tab RIGEDI with request [" + (reqDto != null ? reqDto.toString() : null) + "]", e); responseBuilder = Response.serverError().entity(e.getMessage()); } return responseBuilder.build(); } </code></pre> <p>The problem is that the response arrives correctly to the client but then nothing happens: I am expecting that the browser shows the download dialog (example: in chrome I expect the bottom bar of downloads to appear with my file).</p> <p>What am I doing wrong?</p> </div>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页