如何使用Java以块的形式上传大文件?

2022-09-04 23:05:30

我需要使用Java以块的形式上传一个大文件。

是否有任何我可以参考的示例代码?


答案 1

*可以使用 plupload 完成。下面是示例。我的索引.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 -->

我的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();
                }
            }
        }
    }
}

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

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


答案 2

下面是使用块上传文件的本机 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();
}

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