【问题标题】:Downloading csv file from server从服务器下载 csv 文件
【发布时间】:2012-10-26 14:57:30
【问题描述】:

我有一个系统,其中前端使用 javascript/ajax,后端使用 REST(jersey) 编写。

我想使用我的系统下载文件。我搜索了各种论坛并实现了 REST web 方法如下:

@POST
@Produces({"text/csv"})
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("getcsv")
public Response  getcsv(
        @FormParam("usernamecsv") String userid,
        @FormParam("filename") String filename
        )
{
    final File fobj = new File("c:/" +userid + "/output/" + filename);
    try
    {
        final FileInputStream f =  new FileInputStream(fobj);
ContentDisposition cd =  
        ContentDisposition.type("file").fileName(fobj.toString()).build(); 
Response response = Response
.ok()
.lastModified(new Date(fobj.lastModified()))
.type("application/octet-stream")
.header("Content-Disposition", cd)
.entity(f)
.build();
return response;
    }
    catch (FileNotFoundException e1)
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    return null;

}

最初我使用了 StreamingOutput 类并为它实现了 write 方法。在那个方法中,我返回了从文件中读取的字符串。但我发现这与上述实现没有区别。两者都返回文件内的字符串。

在我的前端,这就是我所做的

<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
function fun1()
{
$.ajax({
    url: '/RestWSGS/jersey/UserAuthentication/getcsv',
    async: false,
    data: $('#form2').serialize(),
    type: 'POST',
    cache: false,
    contentType: "application/x-www-form-urlencoded",
    processData: false,
    dataType: "text",
    success: function(data)
     {
        var iframe;
        iframe = document.getElementById("hiddenDownloader");
        if (iframe === null)
        {
            var iframe;
            iframe = document.getElementById("hiddenDownloader");
            if (iframe === null)
            {
                iframe = document.createElement('iframe');  
                iframe.id = "hiddenDownloader";
                //iframe.style.visibility = 'hidden';
                $("#mydiv").append(iframe);
            }
            iframe.src = "http:\\localhost:8080\\c:\abc@abc.com#26 8 2012 13 5 49/gr1/output/test.csv";  
//iframe.src = data; 

        }

        alert('Hi');

     }
 });
}
$(function()
        {
            $(document).delegate("#mydiv","click",function(ev)
            {
            fun1();

            });
        });

</script>
</head>
<body>
<div id="mydiv" style='position:absolute;width:20px;height:20px;background:black'></div>
<form id="form2" enctype="multipart/form-data" method="post" >
 <input id ="usernamecsv" name="usernamecsv" type="hidden"  value="abc@abc.com#26 8 2012 13 5 49/gr1"/>
  <input id ="filename" name="filename" type="hidden"  value="test.csv" />
</form>

</body>
</html>

我的问题是,如果我将 iframe.src 与数据变量一起分配,我会收到未找到文件的响应(尽管数据变量包含文件的内容)

如果我将 web 服务的 uri(我已经给 ajax 调用)提供给 iframe.src,我不知道我将如何发送参数。

我确实需要向用户显示下载提示并允许他将文件保存到本地文件系统。我认为我的 REST 也不正确,因为它应该在 POST 期间在 firebug 中显示一个文件对象,而不是文件的内容!

我可以只返回字符串并用它填充任何 textarea/ div,然后要求用户将其复制粘贴到他的文件中!但这看起来既不流畅也不优雅!

请帮忙, 卡维塔

编辑: 尝试更改 @Produces 并将 Response.type() 输入为“application/csv”以及“application/something”,但它总是尝试将服务器返回的文件内容附加到当前 url 并打开搜索为文件明显找不到!!!

编辑: 我尝试在 REST 中将 POST 转换为 GET 并使用返回的数据。然后它返回一个 DOCUMENT 但仍然无法打开文件

【问题讨论】:

  • 如果你通过浏览器点击资源,你会得到文件吗?
  • 是什么给出了 contentType: "text/csv", ?
  • @roasted @Produces({"text/csv"}) 注释就可以了。
  • 通过萤火虫查看的帖子显示返回的 csv 内容。
  • @BanksySan 表示调用网络服务??

标签: jquery ajax rest


【解决方案1】:

您的@Produces 标签与您设置的内联类型冲突。如果你们都让他们application/octet-stream 我期待更好的结果。

【讨论】:

  • 这是在我使用 iframe.src = data 并更改后给我的@produces 到 app/oct.. 但它仍然没有要求我保存下载。我还在 ajax 调用中更改了 dataType:“application/octet-stream”
  • Accepts 标头只是难题的一部分。浏览器也会对响应的内容类型做出反应。
【解决方案2】:

经过大量 RnD,我想我找到了解决问题的方法。这可能不是理想的解决方案,如果有任何重大问题,请告诉我。

基本上我尝试访问服务器上的文件,但只能从 docroot 文件夹(PATH = C:\glassfish3\glassfish\domains\domain1\docroot)访问它。所以我意识到我必须将我的文件从服务器上的任何地方复制到这个位置。我在 Web 服务中做到了这一点。我在某处阅读并试图从 Web 服务发送文件本身。在此更改之后这是错误的,我只发回了一个纯文本,其中包含相对于 docroot 的路径。

然后有另一个挫折,因为我的文件必须在一个文件夹中,并且文件夹名称包含一个 # 字符。似乎 # 是不允许的,并且 iframe 只是不会要求我下载!

现在我修改了我的代码如下: 休息:

@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("getcsv")
public String  getcsv(
        @FormParam("usernamecsv") String userid,
        @FormParam("filename") String filename
        )
{
    System.out.println("1 = " + getClass().getResource("/" +getClass().getName().substring(
            0, getClass().getName().indexOf("."))).getPath());
    System.out.println("2 = " + getClass().getResource("/" +getClass().getName().substring(
            0, getClass().getName().indexOf("."))).getPath() + "../../../../../docroot/" + userid + "/" + filename);
    final File fobj = new File("c:/" +userid + "/output/" + filename);
    try
    {
        final FileInputStream f =  new FileInputStream(fobj);
    int content;
         ByteArrayOutputStream b = new ByteArrayOutputStream();
        try
        {
            while ((content = f.read()) != -1) 
            {
                //b[j] = 0;
                // convert to byte
                b.write(content);
            }

        } catch (IOException e)
        {
            e.printStackTrace();
        } 
        finally 
        {
            try 
            {
                if (f != null)
                    f.close();
            } catch (IOException ex) 
            {
                ex.printStackTrace();
            }

        }
        File f1 =  new File( getClass().getResource("/"+getClass().getName().substring(
                0, getClass().getName().indexOf("."))).getPath() + "../../../../../docroot/" + userid.substring(0,userid.indexOf("#")) + "/" );
        f1.mkdirs();
        try
        {
        boolean f2 = new File(getClass().getResource("/" +getClass().getName().substring(
                0, getClass().getName().indexOf("."))).getPath() + "../../../../../docroot/" +  userid.substring(0,userid.indexOf("#")) + "/" + filename).createNewFile();
        System.out.println(f2);

        }
        catch (IOException e2)
        {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
    FileOutputStream fout = new FileOutputStream(new File(getClass().getResource("/" +getClass().getName().substring(
            0, getClass().getName().indexOf("."))).getPath() + "../../../../../docroot/" +  userid.substring(0,userid.indexOf("#")) + "/" + filename));
    try
    {
        fout.write(b.toByteArray());
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
        try
        {
            fout.close();
        }
        catch (IOException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }
    try
    {
        fout.close();
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
}
    catch (FileNotFoundException e1)
    {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    return "/" +  userid.substring(0,userid.indexOf("#")) + "/" + filename;

我的客户端代码:

<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
function fun1()
{
$.ajax({
    url: '/RestWSGS/jersey/UserAuthentication/getcsv',
    async: false,
    data: $('#form2').serialize(),
    type: 'POST',
    cache: false,
    contentType: "application/x-www-form-urlencoded",
    processData: false,
    dataType: "text",
    success: function(data)
     {
        var iframe;
        iframe = document.getElementById("hiddenDownloader");
        if (iframe === null)
        {
            var iframe;
            iframe = document.getElementById("hiddenDownloader");
            if (iframe === null)
            {
                iframe = document.createElement('iframe');  
                iframe.id = "hiddenDownloader";
                //iframe.style.visibility = 'hidden';
                $("#mydiv").append(iframe);
            }


        }
        iframe.src = data;  
        alert('Hi');

     }
 });
}
$(function()
        {
    $(document).delegate("#hiddenDownloader","onload",function(ev)
            {
        alert('in onload');
            });

            $(document).delegate("#mydiv","click",function(ev)
            {
            fun1();

    });
        });
    </script>
</head>
<body>
<a id ='myhref'  href=""></a>
<div id="mydiv" style='position:absolute;width:20px;height:20px;background:black'></div>
<form id="form2" enctype="multipart/form-data" method="post" >
 <input id ="usernamecsv" name="usernamecsv" type="hidden"  value="abc@abc.com#26 8 2012 13 5 49/gr1"/>
  <input id ="filename" name="filename" type="hidden"  value="test.csv" />
</form>

    </body>
</html>

希望有人觉得它有用!! 感谢您的投入!

卡维塔

【讨论】:

  • 下载的文件有问题。该文件实际上并没有在我的解决方案中返回,只有从 docroot 开始的路径。有时它会出现字符编码错误并且不下载文件。 “未声明框架文档的字符编码。如果在没有框架文档的情况下查看该文档,则该文档可能看起来不同。”这可能是由于未设置文件数据的内容类型。有什么建议吗??
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
  • 2017-03-06
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
相关资源
最近更新 更多