Android NDK:使用 NDK 上传文件

Posted

技术标签:

【中文标题】Android NDK:使用 NDK 上传文件【英文标题】:Android NDK: File Upload using NDK 【发布时间】:2012-08-28 10:58:07 【问题描述】:

有没有使用 NDK 将文件从 SD 上传到服务器的源代码?或任何其他方法上传大文件而不获取

Out Of Memory Exception

如果可以,请给我链接?

下面的代码是我使用的代码,但我得到了内存不足异常

 private void UploadFileByClient(LocalFileVO localFileVO)


        try

            File uploadFile = new File(
                    (localFileVO.getFolderPath() + "/" + localFileVO.getFileName()));

            HttpClient    client = new DefaultHttpClient();

            final HttpResponse resp; 
            final HttpClient httpClient = new DefaultHttpClient(); 
            final HttpPut post = new HttpPut("https://qa2-talos-vip-mexico.symnds.com/fileservice/files/");
            post.setHeader("User-Agent", "Mexico/1.0.0.57/android");
            post.setHeader("Content-Type", localFileVO.getMimeType());
            post.setHeader("Authorization", TOKEN);
            post.setHeader("x-mexico-endpointid", GUID);
            post.setHeader("x-mexico-filehash", localFileVO.getFileHash());
            post.setHeader("x-mexico-filesize", localFileVO.getSize());

            if (!TextUtils.equals("0", localFileVO.getFolderId()))
                post.setHeader("x-mexico-folder", localFileVO.getFolderId());

            post.setHeader("x-mexico-filename", localFileVO.getEncodedFileName());
            post.setHeader("Expect", "100-continue");
            post.setHeader("x-mexico-modtime",
                    String.valueOf(System.currentTimeMillis() / 1000));



//          ParcelFileDescriptor fileDescriptor = this.getContentResolver().openFileDescriptor(Uri.parse(uploadFile.getAbsolutePath()), "r"); 
//          InputStream in = this.getContentResolver().openInputStream(Uri.parse(uploadFile.getAbsolutePath()));
            InputStream in = new FileInputStream(uploadFile);

            CountingInputStreamEntity entity = new CountingInputStreamEntity(in, uploadFile.length()); 
            entity.setUploadListener(this);
            post.setEntity(entity); 
            resp = httpClient.execute(post); 
            if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK)  
                System.out.println("=======================Got the response from server============================");
            


        catch(Exception e)
            System.out.println("==============Failed using HttpClient================="+e.getMessage());
        

    

   private int uploadFile( LocalFileVO localFileVO) throws IOException 


       UploadFileByClient(localFileVO);

      if(true)
          return 0;
      

        File uploadFile = new File((localFileVO.getFolderPath() + "/" + localFileVO.getFileName()));


        System.setProperty("http.keepAlive", "false");

        int     code = 0;
        try

        HttpURLConnection urlConnection; 

        URL url = new URL("https://qa2-talos-vip-mexico.symnds.com/fileservice/files/");
    //  URL url = new URL("https://zpi.nortonzone.com/fileservice/files/");

        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setConnectTimeout(30000);
        urlConnection.setRequestProperty("Host", url.getHost());
        // urlConnection.setRequestProperty("Connection", "Keep-Alive");
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        urlConnection.setUseCaches(false);
        urlConnection.setInstanceFollowRedirects(false);
    //  urlConnection.setChunkedStreamingMode(1024);
        urlConnection.setFixedLengthStreamingMode(Integer.parseInt(localFileVO.getSize()));
        //urlConnection.setChunkedStreamingMode(1024);

        urlConnection.setRequestMethod("PUT");
        urlConnection.setRequestProperty("User-Agent", "Mexico/1.0.0.57/android");
        urlConnection.setRequestProperty("Content-Type", localFileVO.getMimeType());
        //urlConnection.setRequestProperty("Content-Length", localFileVO.getSize());
        urlConnection.setRequestProperty("Authorization", TOKEN);
        urlConnection.setRequestProperty("x-mexico-endpointid", GUID);
        urlConnection.setRequestProperty("x-mexico-filehash", localFileVO.getFileHash());
        //urlConnection.setRequestProperty("x-mexico-filesize", localFileVO.getSize());

        if (!TextUtils.equals("0", localFileVO.getFolderId()))
            urlConnection.setRequestProperty("x-mexico-folder", localFileVO.getFolderId());

        urlConnection.setRequestProperty("x-mexico-filename", localFileVO.getEncodedFileName());
        urlConnection.setRequestProperty("Expect", "100-continue");
        urlConnection.setRequestProperty("x-mexico-modtime",
                String.valueOf(System.currentTimeMillis() / 1000));

        bufferOutputStream = new BufferedOutputStream(urlConnection.getOutputStream(),BSIZE);
    //  CountingOutputStream cOutStream = new CountingOutputStream(bufferOutputStream);

        FileInputStream fileInputStream = new FileInputStream(uploadFile);

        long startTime = System.currentTimeMillis();
        try
            int totalSize = 0;

             while (true) 
                   synchronized (chunks) 
                        int amountRead = fileInputStream.read(chunks);
                        System.out.println("========amount read========="+amountRead);
                        if (amountRead == -1) 
                              break;
                        
                        bufferOutputStream.write(chunks, 0, amountRead);
                        bufferOutputStream.flush();
                  
             
            System.out.println("================================TotalSize " + totalSize);
            bufferOutputStream.flush();
             bufferOutputStream.close();
             fileInputStream.close();
            catch(Exception e)
                e.printStackTrace();
            
        long endTime = System.currentTimeMillis();
        System.out.println("=============================================Writing time ==========================================================" + (endTime - startTime)); 
        //code = urlConnection.getResponseCode();

        InputStream inputStream  = urlConnection.getInputStream();



    long endTime1 = System.currentTimeMillis();
    System.out.println("Time to get the response is  " + (endTime1 - endTime)); 
    // progressBar.setProgress(100);
        System.out.println("=================Response code is ================="+code);
        urlConnection.disconnect();
        //fileInputStream.close();

        catch(Exception e)
            System.out.println("========================Exception occured=================="+e.getMessage());
        
        return code;

    

谢谢你

【问题讨论】:

还有,到目前为止你尝试了什么? 我尝试使用 SDK 即 Fileinputstream 和 bufferedoutputstream 进行读写。仅使用这个我得到了 OUT OF MEMORY EXCEPTION(尝试上传 20MB zip 文件) 好,你应该上传那个代码,这样我们才能更好地帮助你亲爱的:) 我用代码编辑了我的问题 好的,如果有的话,也上传错误日志。 【参考方案1】:

您不需要 NDK。如果没有您的代码,我只能建议有将整个文件读入缓冲区的代码。这是错误的。执行以下操作: 分小部分读取文件并将这些部分一一发送到输出流(从连接中获取)

FileInputStream fileInputStream = new FileInputStream(new File(pathToOurFile) )
..
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();

// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);

// Enable POST method
connection.setRequestMethod("POST");

connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
....
outputStream = new DataOutputStream( connection.getOutputStream() );
....
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0)

outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);


outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

// Responses from the server (code and message)
serverResponseCode = connection.getResponseCode();
serverResponseMessage = connection.getResponseMessage();

fileInputStream.close();
outputStream.flush();
outputStream.close();

【讨论】:

先生,我有一个疑问.. 此代码不会显示任何 Out Of Memory Exception ? bcoz iam 试图上传一个非常大的文件,大小约为 Min 20 MB - Max 150 MB 我在这里没有工作示例,但是基于这种方法的应用程序可以很好地上传视频文件。如果我没记错的话,它是前一段时间用谷歌搜索的,我在这里重新找到了这个样本coderzheaven.com/2012/03/29/… sir 代码对于 5MB 文件很好,但是当我使用 20MB 文件时,应用程序崩溃了.. 帮助我【参考方案2】:

您似乎错过了 setChunkedStreamingMode(int) 调用 来自:http://developer.android.com/reference/java/net/HttpURLConnection.html 发布内容 要将数据上传到 Web 服务器,请使用 setDoOutput(true) 配置输出连接。 为了获得最佳性能,您应该在预先知道主体长度时调用 setFixedLengthStreamingMode(int),或者在不知道时调用 setChunkedStreamingMode(int)。否则 HttpURLConnection 将被强制在内存中缓冲完整的请求正文,然后再传输,浪费(并且可能耗尽)堆并增加延迟。

但是您的内容太大而无法缓冲。

【讨论】:

先生,我无法理解 body length 一词(当预先知道 body 长度时)..您是否指定了文件的大小 先生,我试过 setChunkedStreamingMode(1000*1024) 但还是同样的错误。

以上是关于Android NDK:使用 NDK 上传文件的主要内容,如果未能解决你的问题,请参考以下文章

android开发,怎么使用ndk编译成.so文件

android ndk是啥

Android NDK系列- 文件拆分与合并

Android NDK系列- 文件拆分与合并

Android NDK“ndk-build”被识别为内部或外部命令批处理文件

Android NDK,错误:(165, 0) 原因:找不到 ndk-build 二进制文件