【问题标题】:Saved ZIP File gets Corrupted (from an Android App to an IIS Server)保存的 ZIP 文件损坏(从 Android 应用程序到 IIS 服务器)
【发布时间】:2013-02-01 08:24:45
【问题描述】:


trying to send an XML 文件从我的客户端应用程序(在 Android 上)传输到服务器端(IIS 7)之后。我没有得到 XML 文件的文件名,而只是得到了内容。
现在我意识到,简单地传输纯 XML 文件会非常繁重(当我将几乎所有应用程序的数据同步到服务器之后)。

- 现在我正在寻求从我的客户端应用程序向服务器端发送一个压缩文件。
- XML 文件被完美地压缩到原来大小的一半以下。正在使用HTTP POST 方法发送文件,直接使用FileEntity使用MultiPart(这可能是个问题)。

更新 2: 添加了我自己的答案(效果更好:D)。

更新:添加了客户端代码。

问题:
- zip 文件被保存在服务器端,但是当我打开它时,winrar/7zip 给了我一个错误,提示 unexpected end of archive.

我提到了 nearly similar problem,但我在 .NET 上处于劣势在C# 中也进行了开发:(所以不能真正使用确切的代码(丢失、未初始化的变量等)。此外,线程已经有 4 年历史了,我非常不希望有人会回应在那里。

我现有的服务器端代码:

string fileName = "D:\\newZIPfile.zip";
        Stream myStream = Request.InputStream;
        byte[] message = new byte[myStream.Length];
        myStream.Read(message, 0, (int)myStream.Length);
        string data = System.Text.Encoding.UTF8.GetString(message);

        using (FileStream fs = new FileStream(fileName, FileMode.Create))
        {
            using (StreamWriter writer = new StreamWriter(fs, System.Text.Encoding.UTF8))
            {
                writer.Write(data);
            }
        }

我的客户端代码:

 File file2send = new File(newzipfile);

                String urlString = "http://192.168.1.189/prodataupload/Default.aspx";       // FOR TEST
                HttpParams httpParams = new BasicHttpParams();
                int some_reasonable_timeout = (int) (30 * DateUtils.SECOND_IN_MILLIS);

                HttpConnectionParams.setConnectionTimeout(httpParams, some_reasonable_timeout);

                HttpClient client = new DefaultHttpClient(httpParams);
                HttpPost post = new HttpPost(urlString);

                //System.out.println("SYNC'ing USING METHOD: " + post.getMethod().toString());
             try {
                   //OLD FILE-ENTITY MECHANISM >
                    FileEntity fEntity = new FileEntity(file2send, "application/zip");

                    //NEW (v1.5) INPUTSTREAM-ENTITY MECHANISM >
                    //InputStreamEntity fEntity = new InputStreamEntity(new FileInputStream(newzipfile), -1);
                   // fEntity.setContentType("application/zip");
                    post.setEntity(fEntity);

                    HttpResponse response = client.execute(post);
                    resEntity = response.getEntity();
                    res_code = response.getStatusLine().getStatusCode();            
                    final String response_str = EntityUtils.toString(resEntity);
                    if (resEntity != null) {        
                        Log.i("RESPONSE",response_str);
            //...

我该如何解决这个问题? :(

【问题讨论】:

  • 服务器的操作系统是什么?我在win2k3服务器上有类似的问题。通常编码访问仍然有效。尝试将文件发送到你的 win7 或任何电脑(从服务器),看看它是否仍然损坏。
  • @efkah ..在几分钟内发布答案:D

标签: c# java android asp.net http


【解决方案1】:

我会说问题是由于将代码中的 ZIP 文件(二进制)转换为 UTF-8 流所致。

尝试将服务器端代码替换为以下内容:

string fileName = "D:\\newZIPfile.zip";

using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
    byte[] buffer = new byte[32768];
    int read;
    while ((read = Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        fs.Write (buffer, 0, read);
    }
}

这会将接收到的输入流写入 ZIP 文件。

要接收客户端 ZIP 文件名,一种可能的方法是更改​​行

String urlString = "http://192.168.1.189/prodataupload/Default.aspx";

类似于:

String urlString = "http://192.168.1.189/prodataupload/Default.aspx?CLIENTFILENAME=" + 
    urlEncodedFilename;

因此您可以使用Request.Params 属性访问参数。

警告:不要相信客户端发送的文件名(有人可以操纵它!)。对参数进行严格的清理/验证!

【讨论】:

  • 感谢您发布答案。 :) 但请务必在下面查看我的答案。你能告诉我我的回答可能有什么问题吗? :|
  • 好吧,据我所知,两个答案(或多或少)相同。除了我的回答可能会产生错误之外。假设 stream.read 在一次调用中读取整个流是不安全的(我将对其进行编辑)。除了这个问题,我更喜欢我的解决方案,因为它更紧凑,更易于阅读/维护。
  • 有什么方法可以读取 zip 文件的文件名吗?就像我在标题中传递它一样..?实际上,我确实在我的客户端应用程序的标头中传递了它,并且在从Request.Params 读取它时,服务器端代码无法获取它。始终返回 null。
  • 我更新了我发布的代码 sn-p 以提高效率。它以最大复制网络流。 32K 块到文件输出。 Request.Params 保持为空,因为标头信息不是属性的一部分。
  • 感谢它现在工作得很好!此外,我已经大量更新了我的客户端代码,因此发送的文件名是动态的,并将在服务器端进行验证 :) 其次,设置缓冲区是你得到的重要事情! :)
【解决方案2】:

所以这个问题一直困扰着我到目前为止所经历的许多论坛/线程中的很多人。

这是我所做的:
- 将客户端更改为具有binary/octet-stream 内容类型。

- 将服务器端代码更改为: 更新:

if(Request.InputStream.Length < 32768) {
        Request.ContentType = "binary/octet-stream";
        Stream myStream = Request.InputStream;
        string fName = Request.Params["CLIENTFILENAME"];
        //string fName = Request.Params.GetValues("zipFileName");

        int iContentLengthCounter = 0;
        int maxlength = (int) myStream.Length;
        byte[] bFileWriteData = new byte[maxlength];
        string fileName = "D:\\"+ fName +".zip";

        //FileStream oFileStream = new FileStream();

        while (iContentLengthCounter < maxlength)
       {
           iContentLengthCounter += Request.InputStream.Read(bFileWriteData, iContentLengthCounter, (maxlength - iContentLengthCounter));
       }
        System.IO.FileStream oFileStream = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
       oFileStream.Write(bFileWriteData, 0, bFileWriteData.Length);

        oFileStream.Close();
       Request.InputStream.Close();
    }
    else
    {
    }

基本上..我没有收集数据。到它的长度。 (答案需要编辑……稍后再做)

【讨论】:

  • @efkah 是的,我的和 GeneSys 都按预期工作! (现在我只是想进一步改进它......要添加的功能)。 :)
猜你喜欢
  • 1970-01-01
  • 2013-05-05
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多