如何使用 Java 分块上传大文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6074516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:12:11  来源:igfitidea点击:

How could I upload a large file in chunks using Java?

javafilefile-upload

提问by dojomedojo

I need to upload a large file in chunks using Java.

我需要使用 Java 分块上传一个大文件。

Is there any sample code I can refer to?

有没有我可以参考的示例代码?

回答by Ashutosh Jha

*It can be done using plupload. Here is sample. My index.html is as under:-

*它可以使用plupload完成。这是示例。我的 index.html 如下:-

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Upload</title>
    <!-- production -->
    <script type="text/javascript" src="js/plupload.full.min.js"></script>
    <!-- debug 
    <script type="text/javascript" src="../js/moxie.js"></script>
    <script type="text/javascript" src="../js/plupload.dev.js"></script>
    -->
    </head>
    <body style="font: 13px Verdana; background: #eee; color: #333">
    <div id="filelist"></div>
    <br />
        <button id="pickfiles" >Select file</button> 
        <button id="uploadfiles" >Upload</button>
        <div id="container">
    </div>
    <br />
    <pre id="console"></pre>
    <script type="text/javascript">
    // Custom example logic
    var uploader = new plupload.Uploader({
        runtimes : 'html5',
        browse_button : 'pickfiles', // you can pass an id...
        container: document.getElementById('container'), // ... or DOM Element itself
        url : 'UploadAction',//upload.php
        chunk_size : '1mb',
        method:'POST',
        flash_swf_url : 'js/Moxie.swf',
        silverlight_xap_url : 'js/Moxie.xap',

        filters : {
            max_file_size : '100gb',
            mime_types: [
                {title : "Image files", extensions : "jpg,gif,png"},
                {title : "Zip files", extensions : "zip,txt,vmdk"}
            ]
        },
        init: {
            PostInit: function() {
                document.getElementById('filelist').innerHTML = '';
                document.getElementById('uploadfiles').onclick = function() {
                    uploader.start();
                    return false;
                };
            },
            FilesAdded: function(up, files) {
                plupload.each(files, function(file) {
                    document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';
                });
            },
            UploadProgress: function(up, file) {
                document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
            },
            Error: function(up, err) {
                document.getElementById('console').appendChild(document.createTextNode("\nError #" + err.code + ": " + err.message));
            }
        }
    });
    uploader.init();
    </script>
    </body>
    </html>
<!-- end snippet -->

My java backend code(Servlet) is as under:-

我的java后端代码(Servlet)如下:-

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
public class UploadAction extends HttpServlet {
    private static final long serialVersionUID = 3447685998419256747L;
    private static final String RESP_SUCCESS = "{\"jsonrpc\" : \"2.0\", \"result\" : \"success\", \"id\" : \"id\"}";
    private static final String RESP_ERROR = "{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}";
    public static final String JSON = "application/json";
    public static final int BUF_SIZE = 2 * 1024;
    public static final String FileDir = "/home/asjha/uploads/";

    private int chunk;
    private int chunks;
    private String name;
    private String user;
    private String time;
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String responseString = RESP_SUCCESS;
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);

        if(isMultipart){
            ServletFileUpload upload = new ServletFileUpload();
            try {
                FileItemIterator iter = upload.getItemIterator(req);
                while (iter.hasNext()) {
                    FileItemStream item = iter.next();
                    InputStream input = item.openStream();
                    // Handle a form field.
                    if(item.isFormField()){
                        String fileName = item.getFieldName();
                        String value = Streams.asString(input);
                        if("name".equals(fileName)){
                            this.name = value;
                        }else if("chunks".equals(fileName)){
                            this.chunks = Integer.parseInt(value);
                        }else if("chunk".equals(fileName)){
                            this.chunk = Integer.parseInt(value);
                        }else if("user".equals(fileName)){
                            this.user = value;
                        }else if("time".equals(fileName)){
                            this.time = value;
                        }
                    }

                    // Handle a multi-part MIME encoded file.
                    else {
                        File dstFile = new File(FileDir);
                        if (!dstFile.exists()){
                            dstFile.mkdirs();
                        }

                        File dst = new File(dstFile.getPath()+ "/" + this.name);

                        saveUploadFile(input, dst);
                    }
                }
            }
            catch (Exception e) {
                responseString = RESP_ERROR;
                e.printStackTrace();
            }
        }

        // Not a multi-part MIME request.
        else {
            responseString = RESP_ERROR;
        }

        if(this.chunk == this.chunks - 1){
            System.out.println("name"+this.name);
        }
        resp.setContentType(JSON);
        byte[] responseBytes = responseString.getBytes();
        resp.setContentLength(responseBytes.length);
        ServletOutputStream output = resp.getOutputStream();
        output.write(responseBytes);
        output.flush();
    }
    private void saveUploadFile(InputStream input, File dst) throws IOException {
        OutputStream out = null;
        try {
            if (dst.exists()) {
                out = new BufferedOutputStream(new FileOutputStream(dst, true),
                        BUF_SIZE);
            } else {
                out = new BufferedOutputStream(new FileOutputStream(dst),
                        BUF_SIZE);
            }
            byte[] buffer = new byte[BUF_SIZE];
            int len = 0;
            while ((len = input.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != input) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Please refer to plupload for details and on github you can see sample projects by jakobadam and rocky.

有关详细信息,请参阅 plupload,在 github 上您可以看到 jakobadam 和 Rocky 的示例项目。

Please let me know if multiple file upload is required. Using plupload we can upload any number of files of any sizes. This sample is for single file upload of very large size. dont forget to include plupload.full.min.js. Hope this helps*emphasized text**

如果需要上传多个文件,请告诉我。使用 plupload 我们可以上传任意数量的任意大小的文件。此示例适用于非常大的单个文件上传。不要忘记包含 plupload.full.min.js。希望这有助于*强调文字**

回答by stenix

Here is an example of native Java code that uploads a file using chunks:

以下是使用块上传文件的原生 Java 代码示例:

final String       LF = "\r\n"; // Line separator required by multipart/form-data. Can be static class constant
final String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.

HttpURLConnection connection = (HttpURLConnection) new URL("http://some.com/upload").openConnection();
try {
    connection.setDoOutput(true);
    connection.setChunkedStreamingMode(4096);
    connection.setRequestMethod("POST");
    connection.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    connection.addRequestProperty("Accept", "application/json");
    connection.addRequestProperty("Authorization", myToken);
    try (OutputStream os = connection.getOutputStream();
            Writer writer = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
        writer.append("--").append(boundary).append(LF);
        writer.append("Content-Disposition: form-data; name=\"dataFile\"; filename=\"file.zip\"").append(LF);
        writer.append("Content-Type: application/zip").append(LF);
        writer.append(LF);
        writer.flush();

        // Write body
        writeBinaryBody(os);
        writer.append(LF).append("--").append(boundary).append("--").append(LF);
        writer.flush();
        os.flush();
    }
    if (200 != connection.getResponseCode()) {
        try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
            // Handle error here
        }
    }
} finally {
    connection.disconnect();
}

The code in this example is based on this answerabout http file upload from java. The difference is the call to connection.setChunkedStreamingMode(4096);that defines that chunked streaming should be used.

此示例中的代码基于有关从 java 上传 http 文件的答案。不同之处在于对connection.setChunkedStreamingMode(4096);定义应使用分块流的调用。

回答by parthipang

If you are using Java , use Arivus Nioserver gradle dependency -> compile 'org.arivu:nioserver:1.0.3'. No file size constraint.

如果您使用的是 Java,请使用 Arivus Nioserver gradle 依赖项 -> 编译 'org.arivu:nioserver:1.0.3'。没有文件大小限制。

回答by Amir Afghani

You can simply break the file up yourself, send it using the SocketAPI, and re-assemble the file.

您可以自己简单地分解文件,使用SocketAPI发送它,然后重新组合文件。

回答by Jayan

Try Apache Commons upload. It supports streaming, may be suitable for you.

尝试Apache Commons 上传。它支持流式传输,可能适合您。

回答by KyleM

Use a RandomAccessFile. This has already been covered on SO I believe.

使用 RandomAccessFile。这已经在 SO 我相信了。

java file input with rewind()/reset() capability

具有 rewind()/reset() 功能的 java 文件输入

Basically you'd just seek to the starting point, write however many bytes you want to from there, and remember the point you stopped writing from.

基本上,您只是寻找起点,从那里写入您想要的任意字节数,并记住您停止写入的点。