Java – PDF file download using BlockingQueue

I'm trying to download a PDF file using urlconnection Here is how I set up the connection object

URL serverUrl = new URL(url);
urlConnection = (HttpURLConnection) serverUrl.openConnection();
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Content-Type","application/pdf");
urlConnection.setRequestProperty("ENCTYPE","multipart/form-data");
String contentLength = urlConnection.getHeaderField("Content-Length");

I get the input stream from the connection object

bufferedInputStream = new BufferedInputStream(urlConnection.getInputStream());

And write the output stream to the file content

File dir = new File(context.getFilesDir(),mFolder);
if(!dir.exists()) dir.mkdir();
final File f = new File(dir,String.valueOf(documentName));
f.createNewFile();
final bufferedoutputstream bufferedoutputstream = new bufferedoutputstream(new FileOutputStream(f,true)); //true for appendMode

A blocking queue is created so that threads performing read and write operations can access the queue

final BlockingQueue<ByteArrayWrapper> blockingQueue = new ArrayBlockingQueue<ByteArrayWrapper>(MAX_VALUE,true);
final byte[] dataBuffer = new byte[MAX_VALUE];

Now create a thread to read data from InputStream

Thread readerThread = new Thread(new Runnable() {
       @Override
       public void run() {
         try {
            int count = 0;
            while((count = bufferedInputStream.read(dataBuffer,dataBuffer.length)) != -1) {
                 ByteArrayWrapper byteArrayWrapper = new ByteArrayWrapper(dataBuffer);
                 byteArrayWrapper.setBytesReadCount(count);
                 blockingQueue.put(byteArrayWrapper);
             }
             blockingQueue.put(null); //end of file
          } catch(Exception e) {
                 e.printStackTrace();
          } finally {
              try {
                 bufferedInputStream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
       }
 });

The author thread now reads the contents of these files

Thread writerThread = new Thread(new Runnable() {
       @Override
       public void run() {
         try {
            while(true) {
               ByteArrayWrapper byteWrapper = blockingQueue.take();
               if(null == byteWrapper) break;
               bufferedoutputstream.write(byteWrapper.getBytesRead(),byteWrapper.getBytesReadCount());
             }
             bufferedoutputstream.flush();
         } catch(Exception e) {
              e.printStackTrace();
         } finally {
              try {
                 bufferedoutputstream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
         }
      }
});

Finally, start the thread

readerThread.start();
writerThread.start();

In theory, it should read the file from InputStream and save it to the target file However, it actually generates a blank PDF file At other times, it displays invalid PDF format exceptions The file size matches the content length of InputStream Is there anything I missed?

Solution

I'm not familiar with bytearraywrapper It just holds a reference to an array, like this?

public class ByteArrayBuffer {
    final private byte[] data;

    public ByteArrayBuffer(byte[] data) {
        this.data = data;
    }

    public byte[] getBytesRead() {
        return data;
    }

    /*...etc...*/
}

If so This will be a problem: all bytearraywrapper objects are supported by the same array The author was repeatedly covered Even BlockingQueue tries to publish each object safely from one thread to another

Perhaps the simplest fix is to effectively leave the bytearraywrapper unchanged, that is, do not change it after publishing it to another thread Building a copy of the array will be the easiest:

public ByteArrayWrapper(byte[] data) {
    this.data = Arrays.copyOf(data,data.length);
}

Another problem is that "BlockingQueue does not accept empty elements" (see BlockingQueue DOCS), so the "input end" sentinel value does not work Replace null with a

private static ByteArrayWrapper END = new ByteArrayWrapper(new byte[]{});

This problem will be solved in the right place

By making these changes to the copy of the code, I can retrieve a faithful copy of the PDF file

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>