简体   繁体   English

Android将文件大块上传到PHP

[英]Android upload file in chunks to PHP

How can we upload big files in chunks to a PHP server so that if the connection dies, the upload can be resumed at any time. 我们如何将大文件大块地上传到PHP服务器,以便在连接断开时可以随时恢复上传。

Specifically, what libraries are needed in Android to do this? 具体来说,Android需要哪些库来做到这一点?

The users are uploading big files from countries with slow/unstable internet connections. 用户正在从互联网连接缓慢/不稳定的国家/地区上传大文件。 Thank you 谢谢

EDIT 编辑

More info, I'm currently using HTTP POST to upload the whole file at once. 更多信息,我目前正在使用HTTP POST一次上传整个文件。 As the following code shows: 如以下代码所示:

private int uploadFiles(File file) {
        String zipName = file.getAbsolutePath() + ".zip";
        if(!zipFiles(file.listFiles(), zipName)){
            //return -1;
            publishResults(-1);
        }
        //publishProgress(-1, 100);
        HttpURLConnection connection = null;
        DataOutputStream outputStream = null;
        DataInputStream inputStream = null;

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        String serverUrl = prefs.getString("serverUrl", "ServerGoesHere"); // todo ensure that a valid string is always stored
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1 * 1024 * 1024;
        int responseCode = -1;
        try {
            //notif title, undeterministic
            pNotif.setContentText("Zipping complete. Now Uploading...")
                  .setProgress(0, 0, true);
            mNotifyManager.notify(NOTIFICATION_ID, pNotif.build()); // make undeterministic

            //update progress bar to indeterminate
            sendUpdate(0, 0, "Uploading file."); // sendupdate using intent extras

            File uploadFile = new File(zipName);
            long totalBytes = uploadFile.length();
            FileInputStream fileInputStream = new FileInputStream(uploadFile);

            URL url = new URL(serverUrl);
            connection = (HttpURLConnection) url.openConnection();

            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            connection.setRequestMethod("POST");

            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type",
                    "multipart/form-data;boundary=" + boundary);
            outputStream = new DataOutputStream(connection.getOutputStream());
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
            outputStream
            .writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
                    + zipName + "\"" + lineEnd);
            outputStream.writeBytes(lineEnd);

            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            buffer = new byte[bufferSize];
            long bytesUploaded = 0;
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);

            while (bytesRead > 0) {
                bytesUploaded += bytesRead;
                outputStream.write(buffer, 0, bufferSize);
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                //int percentCompleted = (int) ((100 * bytesUploaded) / totalBytes);
                //publishProgress((int)bytesUploaded/1024, (int)totalBytes/1024);

                System.out.println("bytesRead> " + bytesRead);
            }

            //publishProgress(-2, 1); // switch to clean up
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + twoHyphens
                    + lineEnd);
            try {
                responseCode = connection.getResponseCode();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            fileInputStream.close();
            outputStream.flush();
            outputStream.close();
            // Delete the zip file
            new File(zipName).delete();
        } catch (Exception ex) {
            new File(zipName).delete();
            responseCode = -1;
            ex.printStackTrace();
        } 
        return responseCode;
    }

Is there a way to modify this to send it by chunks? 有没有办法修改它以分块发送? Most of the research I've done has not been very clear, sorry 对不起,我所做的大部分研究都不太清楚

It is not a good idea to upload a file in chunks via HTTP, since it is a stateless protocol and you would need to make a new connection for every chunk you want to send to the server. 通过HTTP分块上传文件不是一个好主意,因为它是无状态协议,您需要为要发送到服务器的每个分块建立一个新的连接。 Furthermore, you have to maintain state between this transfers manually and there is no assurance that the files will arrive in the order they are sent. 此外,您必须手动维护两次传输之间的状态,并且不能保证文件将按发送顺序到达。

You should use socket programming with TCP sockets which maintain a connection until the whole file is send. 您应该将套接字编程与TCP套接字一起使用,该套接字将保持连接,直到发送整个文件为止。 You can then push chunks into the socket and they will arrive without loss and in the same order they are fed to the socket. 然后,您可以将块推入套接字,它们将无损失地到达,并且以它们被馈送到套接字的顺序。

I ended up implementing resumable uploads using an SFTP library. 我最终使用SFTP库实现可恢复的上传。 JSch http://www.jcraft.com/jsch/ I upload using SFTP and the library handles the resumable mode. JSch http://www.jcraft.com/jsch/我使用SFTP上传,该库处理可恢复模式。 Example code: 示例代码:

JSch jsch = new JSch();
session = jsch.getSession(FTPS_USER,FTPS_HOST,FTPS_PORT);
session.setPassword(FTPS_PASS);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
channelSftp.cd(FTPS_PATH);

File uploadFile = new File(zipName); // File to upload
totalSize = uploadFile.length(); // size of file

// If part of the file has been uploaded, it saves the number of bytes. Else 0
try {
    totalTransfer = channelSftp.lstat(uploadFile.getName()).getSize();
} catch (Exception e) {
    totalTransfer = 0;
}

// Upload File with the resumable attribute
channelSftp.put(new FileInputStream(uploadFile), uploadFile.getName(), new SystemOutProgressMonitor(), ChannelSftp.RESUME);

channelSftp.exit();
session.disconnect();

With this library I fulfilled all the requirements: resumable uploads and upload progress. 使用此库,我可以满足所有要求:可恢复的上传和上传进度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM